문제
나는 상황이 나를 감싸는 네이티브 C++DLL C++을 위한 최종 사용하여 C#에서.
거기에 몇 가지의 콜백 함수를 일으키는 문제입니다.특히,나는 다음과 같은 예외:
처리되지 않은 형식의 예외가 '시스템이다.런타임입니다.InteropServices.InvalidOleVariantTypeException' 에서 발생 ToadWrapTest.dll
추가 정보:지정된 OLE 변형이 잘못되었습니다.
이 라인의 코드(C++):
public delegate int ManagedCallbackFunction (Object^ inst, const Object^ data);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
System::IntPtr ip1 = IntPtr(pInstance);
System::IntPtr ip2 = IntPtr(temp);
Object^ oInst = Marshal::GetObjectForNativeVariant(ip1);
Object^ oData = Marshal::GetObjectForNativeVariant(ip2);
//invoke the callback to c#
//return m_callbackFn::Invoke(oInst, oData);
return 0;
};
이유는 내가 만들이"중개 콜백"었을 회피하려는 잘못된 변형을 제외되는 것을 때 발생했을 직접 지도하에서 대리인 C#어는 C++코드입니다.으로도 작업,주위에 내가 선언하는 대리인에서는 C#측면과 전달하는 funcptr C++/CLI 래퍼입니다.나는 다음을 전달 중개 funcptr 어는 C++고 데이지 체인 전화를 함께.
내가 무엇을 알고 있는 모든 작품에서는 네이티브 C++에서 세계입니다.문제입니다 매핑 void*관리되는 세계입니다.다음 코드는 native C++버전의 callback:
int (*CallbackFunction) (void *inst, const void *data);
사람이 여기에 도움이 될 수 있습니다,정말 감사드리겠습니다.
해결책
Pinstance와 Pdata가 정말 변형입니까? 그들이 있다면, 나는 당신의 콜백 기능이보다 강력하게 입력 될 것으로 기대합니다.
int (*CallbackFunction)(VARIANT *inst, VARIANT *data);
이 경우 코드에서 실제를 볼 수 있어야합니다. 변종 손으로 확인합니다. 실제로 변형을 얻지 못한다면 (즉, 실제로 무효 * 포인터를 얻는다), 고유 한 의미가 없기 때문에 C# 객체로 바꾸려고해서는 안됩니다. 그들은 intptr로 통과해야합니다. 다른 유형의 고유 한 의미가 있어야한다는 것을 알고 있다면 적절한 유형으로 마샬링해야합니다.
다른 팁
큰 감사를 받침대에 하나입니다!나는 게시 최종 솔루션은 아래 사람은 누구나 다른 사람과 거래하는 제 3 자 재미있는 이처럼 하나입니다!을 주시기 바랍 비평,나와 같은 수행하지 않을 최적화하는 코드입니다.이 여전히 수 있습을 원형 교차로는 솔루션입니다.
첫째,콜백 함수가 되었:
public delegate int ManagedCallbackFunction (IntPtr oInst, IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
큰 소품이다.그것은 그냥 평범한 작동하지 않을 시도하는 경우 캐스팅에서 무효*직접 개체^.를 사용하 IntPtr 및 내 중개 callback:
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
return m_callbackFn->Invoke(IntPtr(pInstance), IntPtr(temp));
};
우리가 마지막으로 작동하는 모델에서 C#쪽으로 몇 마사지기의 개체:
public static int hReceiveTestMessage(IntPtr pInstance, IntPtr pData)
{
// provide object context for static member function
helloworld2 hw = (helloworld2)GCHandle.FromIntPtr(pInstance).Target;
if (hw == null || pData == null)
{
Console.WriteLine("hReceiveTestMessage received NULL data or instance pointer\n");
return 0;
}
// populate message with received data
IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataPacketWrap(pData)));
DataPacketWrap dpw = (DataPacketWrap)GCHandle.FromIntPtr(ip2).Target;
uint retval = hw.m_testData.load_dataSets(ref dpw);
// display message contents
hw.displayTestData();
return 1;
}
내가 언급"마사지"기 때문에 대리인 한정하지 않고 이 콜백 함수하고 내가 무엇인지 모르체 pData 될 때까지 실행 시간(에서 대표 POV).이 문제 때문에,나는 몇 가지 추가 작업을 수행과 pData 개체입니다.저는 기본적으로 과부하가 생성자 내에서 래퍼를 받아들이는 IntPtr.코드가 제공됩를 위한 전체"clarity":
DataPacketWrap (IntPtr dp)
{
DataPacket* pdp = (DataPacket*)(dp.ToPointer());
m_NativeDataPacket = pdp;
};