I have a managed wrapper class that has a delegate to be called from
unmanaged code:
public ref class CmmMessageCallbackWrapper
{
private:
delegate void InternalMessageDelegate( void*,
CmmService::Message::CMessage* );
public:
CmmMessageCallbackWrapper()
{
_InternalMessageCallback = gcnew
InternalMessageDelegate(this,&CmmMessageCallbackWrapper::InternalMessageCallback);
}
void* GetPtrCallback()
{
return
(void*)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(_InternalMessageCallback);
}
private:
void InternalMessageCallback(void* pData,
CmmService::Message::CMessage* pMessageData)
{
return;
}
InternalMessageDelegate^ _InternalMessageCallback;
};
I then setup my unmanaged callback as follows:
bool CMyManagedClass::CallUnmanaged()
{
CmmMessageCallbackWrapper^ Wrapper = gcnew
CmmMessageCallbackWrapper();
FN_MESSAGE_CALLBACK pfnCallback = (FN_MESSAGE_CALLBACK)Wrapper-
>GetPtrCallback();
return _pUnmanagedObj->CallFuncWithCallback(pfnCallback);
}
GetPtrCallback() returns the marshalled function pointer. Problem is
in a release build the callback causes a crash, in debug it is fine.
The only thing I can think of is the 'Wrapper' is garbage collected
before the delegate is called.
Help and advice greatfully received. I'm stuck.
ropo - 21 Nov 2007 16:17 GMT
> I have a managed wrapper class that has a delegate to be called from
> unmanaged code:
[quoted text clipped - 44 lines]
>
> Help and advice greatfully received. I'm stuck.
I think it is a problem of Garbage collection, changing the code to
this:
bool CMyManagedClass::CallUnmanaged()
{
CmmMessageCallbackWrapper^ Wrapper = gcnew
CmmMessageCallbackWrapper();
FN_MESSAGE_CALLBACK pfnCallback =
(FN_MESSAGE_CALLBACK)Wrapper->GetPtrCallback();
bool bRes = _pUnmanagedObj-
>CallFuncWithCallback(pfnCallback);
Wrapper->GetPtrCallback();
return bRes;
}
So that Wrapper is references after the function call, fixes the
problem. Anyone know why?
Mattias Sjögren - 21 Nov 2007 19:08 GMT
>The only thing I can think of is the 'Wrapper' is garbage collected
>before the delegate is called.
If that's the problem, you can add GC::KeepAlive(Wrapper) to the end
of your method to prevent the object from being collected too soon.
Mattias

Signature
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
ropo - 22 Nov 2007 09:12 GMT
On 21 Nov, 19:08, Mattias Sjögren <mattias.dont.want.s...@mvps.org>
wrote:
> >The only thing I can think of is the 'Wrapper' is garbage collected
> >before the delegate is called.
[quoted text clipped - 7 lines]
> Mattias Sjögren [C# MVP] mattias @ mvps.orghttp://www.msjogren.net/dotnet/|http://www.dotnetinterop.com
> Please reply only to the newsgroup.
Brilliant, Thanks that is exactly what I needed