Question

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?

Was it helpful?

Solution

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)) );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top