The .net method that I will get its pointer is:
Get the method pointer so I can call in C++ program.
This works for me but I need to declare delegate for every method.
I want to get rid of doing things over and over again.
In .net side:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void UpdateDelegate(float delta);
public static void* GetUpdatePointer()
{
var delegateInstance = = new UpdateDelegate(Update);
var pfnUpdate = Marshal.GetFunctionPointerForDelegate(delegateInstance);
return (void*)pfnUpdate;
}
public static Update(float delta)=>{...}
In C++ side:
typedef void (_stdcall * FuncPtr)(float);
void foo()
{
//just pseudo-code showing where is the pfnUpdate from.
FuncPtr pfnUpdate = (FuncPtr)GetUpdatePointer();
pfnUpdate(0.01f);
}
In c#, I export GetMethodPointer for my native code. It will return a function pointer to specified method, and this pointer can be invoked by native program via stdcall calling convention.
//avoid gc collect this object
static List<Delegate> KeepReference = new List<Delegate>();
public unsafe static void* GetMethodPointer(string name)
{
System.Reflection.MethodInfo methodInfo = typeof(PhysicsMain).GetMethod(name);
// also mark this delegate with [UnmanagedFunctionPointer(CallingConvention.StdCall)] attribute
Type delegateType = ConstructDelegateTypeWithMethodInfo(methodInfo);
var delegateInstance = Delegate.CreateDelegate(delegateType, methodInfo);
KeepReference.Add(delegateInstance);
return (void*)Marshal.GetFunctionPointerForDelegate(delegateInstance);
}
I need ConstructDelegateTypeWithMethodInfo to create a delegate with the same signature as the specified method. And mark [UnmanagedFunctionPointer(CallingConvention.StdCall)] attribute for it so that can be marshaled as a function pointer.
I think it may using IL, Reflection, even Asm to do this. Or using IL to write the whole GetMethodPointer method.
Finally, I got a solution these days. Firstly, I came across Expression.GetDelegateType
given by this post. But it did't work for me, because Marshal.GetFunctionPointerForDelegate
doesn't support generic delegate type generate by Expression.GetDelegateType
. I thought there might be a clue in implementation of Expression.GetDelegateType
. So, I browsed referencesource and got a internal method called MakeNewCustomDelegate
. This link gives code about how to call the internal method. Things are readily solved!
Edit: I forgot to say, the default unmanaged calling convension of a delegate is stdcall, so we don't need to mark the delegate with [UnmanagedFunctionPointer(CallingConvention.StdCall)] explicitly.