How to pass a delegate or function pointer from C# to C++ and call it there using InternalCall
After some more hours of digging I finally found a (the?) solution.
Basically, what works for the PInvoke approach works here as well, you can pass a function pointer instead of a delegate from C# to C(++).
I'd prefer a solution where you can pass a delegate directly, but you can always add some wrapper code in C# to at least make it look like that.
Solution:
C#:
public delegate void CallbackDelegate(string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void setCallback(IntPtr aCallback);
private CallbackDelegate del;
public void testCallbacks()
{
System.Console.Write("Registering C# callback...\n");
del = new CallbackDelegate(callback01);
setCallback(Marshal.GetFunctionPointerForDelegate(del));
System.Console.Write("Calling passed C++ callback...\n");
}
public void callback01(string message)
{
System.Console.Write("callback 01 called. Message: " + message + "\n");
}
C++:
typedef void (*CallbackFunction)(MonoString*);
void setCallback(CallbackFunction delegate)
{
std::cout << &delegate << std::endl;
delegate(mono_string_new(mono_domain_get(), "Test string set in C++"));
}
Watch out, though: You need to keep the delegate around in C# somehow (which is why I assigned it to "del") or it will be caught by the GC and your callback will become invalid.
It makes sense, of course, but I feel this is easy to forget in this case.
you can pass function pointer as parameter in c++ to c# using intptr_t.
MSDN isn't accurate, below code works.
// c++
static void func(int param)
{
//...
}
void other_func()
{
ptr->SetCallback( reinterpret_cast<intptr_t>(func));
}
// c#
public static mydelegatetype somefunc = null;
public void SetCallback(IntPtr function_pointer)
{
somefunc = (mydelegatetype)
Marshal.GetDelegateForFunctionPointer(function_pointer, typeof(mydelegatetype));
}