dimanche 20 septembre 2020

How to get .net managed method pointer by "MethodName" that can be called on native code

Precondition

The .net method that I will get its pointer is:

  • public static method
  • have no overloads
  • arguments and return value just ValueType (unsafe pointer, primitive type, unmanaged struct)

Reason

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);
}

what I want

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.





Aucun commentaire:

Enregistrer un commentaire