2013-05-13 2 views
6

관리되는 System.Action을 C++/CLI 프로젝트 내부의 관리되지 않는 std :: function으로 변환하고 있습니다. 콜백을 사용한 후에 주어진 IntPtr을 공개해야합니까, 아니면 불필요한가요?Marshal :: GetFunctionPointerForDelegate : 결과를 공개해야합니까?

void MyClass::Execute(System::Action^ callback) 
{   

    IntPtr callbackPtr = Marshal::GetFunctionPointerForDelegate(callback); 
    std::function<void (void)> nativeCallback = static_cast<void (__stdcall *) (void)>(callbackPtr.ToPointer()); 

    m_nativeObject->Execute(wrappedCallback); 

    // should I release callbackPtr here? 
} 

답변

6

호는이 작업을 수행 할 원수 클래스 메서드가 없습니다 : 다음은 조기에 대리인을 배치에서 GC를 방지하는 방법을 포함하여 좋은 기사입니다. 동적으로 생성 된 모든 코드와 마찬가지로이 메서드로 작성된 썽크는 AppDomain과 연결되며 AppDomain이 언로드되면 언로드됩니다.

위임 객체의 경우가 아니라 일반적인 가비지 수집 규칙의 적용을받습니다. 그리고 당신은 조심해야합니다, 덤은 이 아니고이 살아있게합니다. 코드의 버그는 네이티브 코드가 실행 중일 때 대리자를 수집 할 수 있습니다. 당신은 방법의 끝에 코드 줄을 추가해야합니다 :

GC::KeepAlive(callback); 

을 콜백 동안 만 실행() 메소드가 실행으로 될 것이라는 가정으로. 관리되지 않는 코드가이 메서드 호출을 넘어 함수 포인터를 저장하면 유효하게 유지하기 위해 대리자 개체를 어딘가에 저장해야합니다.

+0

m_nativeObject-> Execute (wrappedCallback)가 동기이면? – Notoriousxl

+5

실이 하루를 망칠 것입니다. 글쎄, 주. –

2

포인터를 놓을 필요가 없습니다. 함수에 대한 포인터 (시스템 아키텍처에 따라 32/64 비트 크기)가 이미 있습니다. .net 프레임 워크 인프라 스트럭처가 포인터를 실행하기 위해 더 많은 것을 필요로한다면 모든 메소드에서 동일 할 것이므로 정적으로 할당됩니다 (상태 없음).

관련 문제