Release only problem calling a delegate from unmanaged code
Release only problem calling a delegate from unmanaged code
am 21.11.2007 17:03:32 von ropo
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::Int ernalMessageCallback);
}
void* GetPtrCallback()
{
return
(void*)System::Runtime::InteropServices::Marshal::GetFunctio nPointerForDelegate(_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.
Re: Release only problem calling a delegate from unmanaged code
am 21.11.2007 17:17:51 von ropo
On 21 Nov, 16:03, ropo wrote:
> 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::Int ernalMessageCal-lback);
> }
> void* GetPtrCallback()
> {
> return
> (void*)System::Runtime::InteropServices::Marshal::GetFunctio nPointerForDele-gate(_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.
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?
Re: Release only problem calling a delegate from unmanaged code
am 21.11.2007 20:08:30 von mattias.dont.want.spam
>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
--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Re: Release only problem calling a delegate from unmanaged code
am 22.11.2007 10:12:09 von ropo
On 21 Nov, 19:08, Mattias Sjögren
wrote:
> >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
>
> --
> Mattias Sjögren [C# MVP] mattias @ mvps.orghttp://www.msjogren.net/dotn=
et/|http://www.dotnetinterop.com
> Please reply only to the newsgroup.
Brilliant, Thanks that is exactly what I needed