Reputation: 714
Currently I am working with two layers. One layer is C++/CLI and the other layer is an unmanaged C++ graphics library that I do not have the source to. I pass data to unmanaged code and receive data back in a callback function 'intermediateCallback' when a user moves a manipulator in the unmanaged code.
Below is how I define the delegate type called 'tempFunc'. It takes in nothing and returns nothing. The 'void* userData' parameter of 'intermediateCallback' is what I want to turn back into a delegate instance. This parameter is passed into the unamanged code as a delegate converted to a IntPtr cast to a void*. I can turn the void* back into an IntPtr, but how can I turn that back into a the delegate type 'tempFunc'?
delegate void tempFunc();
//the function that the delegate instance actually points to
void libCoin3D::CenterballDragger::memberCallback()
{
....
}
//the function that the unmanaged code will call and pass data to
void intermediateCallback( void * userData, SoDragger *dragger)
{
System::IntPtr ptr=(System::IntPtr)userData;
tempFunc^ tF=(tempFunc^)ptr;//this line does not work, I want to do something like it
}
Originally, this is how I turned the delegate into a void* when I passed it into unmanaged code.
If tF is a delegate defined by:
tempFunc^ tF=gcnew tempFunc(this,&libCoin3D::CenterballDragger::memberCallback);
I converted it with:
(System::Void*)(System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(tF))
So is it possible to convert void* into tempFunc?
Upvotes: 0
Views: 1451
Reputation: 4815
I solve a similar problem like this:
delegate void tempFunc();
//the function that the delegate instance actually points to
void libCoin3D::CenterballDragger::memberCallback()
{
....
}
//the function that the unmanaged code will call and pass data to
void __stdcall intermediateCallback( void * userData, SoDragger *dragger)
{
using System::Runtime::InteropServices::GCHandle;
GCHandle gch = GCHandle::FromIntPtr((System::IntPtr)userData);
tempFunc^ tF = (tempFunc^)gch.Target;
tF();
gch.Free(); // If the call only once, otherwise it is necessary to keep the pointer and delete it later
}
tempFunc^ tF = gcnew tempFunc(this, &libCoin3D::CenterballDragger::memberCallback);
// pass to unmanaged code
setCallback( &intermediateCallback, (void*)GCHandle::ToIntPtr(GCHandle::Alloc(tF)) );
Upvotes: 3