如何通过 "MethodName" 获取可在本机代码上调用的 .net 托管方法指针
How to get .net managed method pointer by "MethodName" that can be called on native code
先决条件
我将获取其指针的 .net 方法是:
- public静态方法
- 没有过载
- 参数和 return 值只是 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。它将return一个指向指定方法的函数指针,这个指针可以被本地程序通过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方法。
在您的示例中,您假设方法的 class 是已知函数 (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
属性。
这几天终于有办法了。首先,我遇到了 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 给出了关于如何调用内部方法的代码。事情迎刃而解!
编辑:忘了说了,委托的默认非托管调用约定是stdcall,所以我们不需要显式地用[UnmanagedFunctionPointer(CallingConvention.StdCall)]标记委托。
先决条件
我将获取其指针的 .net 方法是:
- public静态方法
- 没有过载
- 参数和 return 值只是 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。它将return一个指向指定方法的函数指针,这个指针可以被本地程序通过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方法。
在您的示例中,您假设方法的 class 是已知函数 (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
属性。
这几天终于有办法了。首先,我遇到了 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 给出了关于如何调用内部方法的代码。事情迎刃而解!
编辑:忘了说了,委托的默认非托管调用约定是stdcall,所以我们不需要显式地用[UnmanagedFunctionPointer(CallingConvention.StdCall)]标记委托。