1

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.

anchur
  • 39
  • 6

2 Answers2

1

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.

anchur
  • 39
  • 6
  • I provided another example how this can be implemented [here](https://stackoverflow.com/a/75188743/15495138) – sunnamed Jan 20 '23 at 19:51
0

In your example you assume that the class of the method is know function (PhysicsMain).

If UpdateDelegate is also known you can use it easily:

Type delegateType = typeof(UpdateDelegate);
var delegateInstance = Delegate.CreateDelegate(delegateType, methodInfo);

But you can also get this type by name only:

Type delegateType = Type.GetType("Namespace.ClassName+UpdateDelegate");
var delegateInstance = Delegate.CreateDelegate(delegateType, methodInfo);

You can look at delegateType.CustomAttributes and verify that the type has UnmanagedFunctionPointer attribute.

Svirin
  • 564
  • 1
  • 7
  • 20
  • Sorry, maybe I didn’t express it clearly. There 's no delegate type called "UpdateDelegate". There's no delegate predefined. Because there were many methods with different signature, I don't want to predefine delegate for each method. I just want to generate the delegate type at runtime using MethodInfo. And actually, the MethodInfo do contains all infomation about constructing a delegate type for this method. But thanks for your help. – anchur Sep 25 '20 at 02:23