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