Release only problem calling a delegate from unmanaged code

R

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::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.
 
R

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::InternalMessageCal-lback);
}
void* GetPtrCallback()
{
return
(void*)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDele-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?
 
M

Mattias Sjögren

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
 
R

ropo

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

Brilliant, Thanks that is exactly what I needed
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top