2013-03-18 3 views
4

관리되지 않는 코드의 문자열을 managed로 전달하는 데 문제가 있습니다. 내 관리되지 않는 클래스에서 (unmanagedClass.cpp) 내가 관리 코드에서 함수에 대한 포인터를 가지고 :관리되지 않는 코드에서 관리되는 문자열 전달

TESTCALLBACK_FUNCTION 한 문자열을 받아 아무 것도 반환하지
TESTCALLBACK_FUNCTION testCbFunc; 

: ITest 인터페이스에서

typedef void (*TESTCALLBACK_FUNCTION)(char* msg); 

관리되지 않는 클래스 inherites을 여기에는 하나의 방법 만 있습니다.

STDMETHOD(put_TestCallBack) (THIS_ 
        LPVOID FnAddress  
      ) PURE; 

managedClass.cs에서이 코드를 작성합니다. :

public class ManagedClass 
{ 
    ITest unmanaged = new unmanagedClass(); 
    public delegate void TestDelegate(string info); 
    ManagedClass() 
    { 
     unmanaged.put_TestCallBack(new TestDelegate(this.Test)); 
    } 
    void Test(string info) 
    { 
      MessageBox.Show(info); 
    } 
} 

[ComImport, Guid("<my guid here>")] 
public class unmanagedClass 
{ 
} 

[ComImport, System.Security.SuppressUnmanagedCodeSecurity, 
Guid("<my guid here>"), 
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface ITest 
{ 
    [PreserveSig] 
    int put_TestCallBack([MarshalAs(UnmanagedType.FunctionPtr), In] Capture.TestDelegate func); 

}

는 비 관리 코드에서 테스트 FUNC를 호출하려면 내가 사용이

(*testCbFunc)("Func Uragan33::Execute has been started!"); 

그러나 managedClass.cs에서 시험 방법은 항상 문자열을받은 호출 할 때. 왜 이런 일이 발생합니까?

감사합니다.

답변

5

호출 규칙이 일치하지 않습니다. C++ 코드의 typedef는 기본 호출 규칙 인 __cdecl을 사용하여 함수 포인터를 선언합니다. 그러나 관리되는 코드에서 대리자의 기본값은 __stdcall입니다.

그렇지 않으면 pinvoke marshaller에 알리기 위해 속성이 필요합니다. 다음과 같이 설정하십시오.

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate void TestDelegate(string info); 

[MarshalAs]를 함수 선언에 놓으십시오. 할 수 있다면 분명히 모든 것이 일치하고, 바람직 수 있습니다 당신의 C++ 코드에서 타입 정의를 수정하는 것이 선호되는 솔루션입니다 :

typedef void (__stdcall * TESTCALLBACK_FUNCTION)(char* msg); 

는 관련없는, 이것은 당신이 필요합니다 버그가 수정합니다 :

unmanaged.put_TestCallBack(new TestDelegate(this.Test)); 

작성한 위임 객체는 가비지 수집기에 표시되지 않습니다. 다음 GC에서 수집되는 경우 네이티브 코드가 콜백을하면 코드가 충돌합니다. 대리자 객체를 어딘가에 저장해야 GC가 항상 참조를 볼 수 있습니다. 클래스의 필드로서, 클래스 객체가 충분히 오랫동안 살아 있어야하거나 정적 변수에 있어야한다는 추가 요구 사항이 있습니다.

위임자 대신 콜백 인터페이스를 선언하면 이러한 모든 문제가 사라집니다. COM 방식.

+0

대단히 감사합니다! – Alekstim

관련 문제