微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过“ MethodName”获取可在本机代码上调用的.net托管方法指针

如何解决如何通过“ MethodName”获取可在本机代码上调用的.net托管方法指针

前提条件

我将获得其指针的.net方法是:

  • 公共静态方法
  • 没有过载
  • 参数和返回值仅是ValueType(不安全的指针,原始类型,非托管结构)

原因

获取方法指针,以便我可以在C ++程序中调用

这对我有用,但是我需要为每个方法声明委托。

我想摆脱一遍又一遍的事情。

在.net端:

[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)=>{...}

在C ++方面:

typedef void (_stdcall *  FuncPtr)(float);
void foo()
{
    //just pseudo-code showing where is the pfnUpdate from.
    FuncPtr pfnUpdate = (FuncPtr)GetUpdatePointer();
    pfnUpdate(0.01f);
}

我想要什么

在c#中,我为我的本机代码导出getmethodPointer。它将返回一个指向指定方法函数指针,并且本机程序可以通过stdcall调用约定来调用此指针。

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

我需要ConstructDelegateTypeWithMethodInfo来创建一个具有与指定方法相同签名的委托。并为其标记[UnmanagedFunctionPointer(CallingConvention.StdCall)]属性,以便可以将其封送为函数指针。

我认为它可能使用IL,Reflection甚至Asm来做到这一点。或使用IL编写整个getmethodPointer方法

解决方法

在您的示例中,您假设方法的类是已知函数(PhysicsMain)。

如果还知道UpdateDelegate,则可以轻松使用它:

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

但是您也可以仅通过名称获得此类型:

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

您可以查看delegateType.CustomAttributes并确认类型具有UnmanagedFunctionPointer属性。

,

最后,这几天我找到了解决方案。首先,我遇到了post给出的Expression.GetDelegateType。但这对我不起作用,因为Marshal.GetFunctionPointerForDelegate不支持Expression.GetDelegateType生成的通用委托类型。我认为Expression.GetDelegateType的实现可能会有一些线索。因此,我浏览了referencesource,并得到了一个名为MakeNewCustomDelegate的内部方法。 link给出了有关如何调用内部方法的代码。事情很容易解决!

编辑:我忘了说了,委托的默认非托管调用约定是stdcall,因此我们不需要明确地用[UnmanagedFunctionPointer(CallingConvention.StdCall)]标记委托。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。