using System;
using System.Runtime.InteropServices;
using System.Reflection;
public struct StructCreatedByUser
{
public int x;
public float anything;
public string name;
}
class Program
{
[DllImport("CppLibrary")]
private static extern void SetPointer(IntPtr ptr);
[DllImport("CppLibrary")]
private static extern void CallCppFunctionWithParam(IntPtr param);
public static void FunctionCreatedByUser(StructCreatedByUser data){
Console.WriteLine(data.x + " " + data.anything + " " + data.name );
}
static void Main()
{
StructCreatedByUser data = new StructCreatedByUser { x = 10, anything = 20.5f, name = "wedf" };
IntPtr param = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(StructCreatedByUser)));
Marshal.StructureToPtr(data, param, false);
IntPtr methodPtr = typeof(Program).GetMethod("FunctionCreatedByUser").MethodHandle.GetFunctionPointer();
SetPointer(methodPtr);
CallCppFunctionWithParam(param);
}
}
#include <iostream>
#include <functional>
#include <string>
typedef void (*FunctionStorage)(void*);
FunctionStorage func;
extern "C" void SetPointer(void* methodPtr) {
func = reinterpret_cast<FunctionStorage>(methodPtr);
}
extern "C" void CallCppFunctionWithParam(void* param) {
func(param);
}
我试图通过使用内存操作直接从 C++ 调用方法来避免在 C# 反射中使用
MethodInfo.Invoke()
带来的性能开销。我的目标是在运行时完全绕过反射。
我成功地在C++中调用了通过反射获得的方法而不传递参数,但是当我尝试传递参数时,我无法让它工作。我怀疑用户定义的方法需要接受
IntPtr
并在内部处理数据转换,但这种方法对用户不友好。理想情况下,与 C++ 和内存管理相关的所有内容都应在后台处理。
这是我的具体问题:
如何将参数(例如结构体)从 C++ 传递到通过反射获得的 C# 方法?
当我尝试传递参数时,没有遇到编译时错误,但在运行时,调用失败。导致此问题的可能原因是什么?
任何有关如何实现这一点的指导或示例将不胜感激。
我的.NET版本是8.0.110
这么多问题:
void*
参数,这意味着您需要通过引用传递结构,因为它对于本机 int 来说太宽了。GetFunctionPointer()
是危险的,在大多数情况下不打算直接使用,因为运行时通常需要根据函数的设计和调用位置来设置蹦床垫片。您需要使用带有 Marshal.GetFunctionPointerForDelegate
的委托来代替。老实说,我很不清楚为什么你不让编组员为你解决这一切。只需使用实际的
delegate
声明一个 ref StructCreatedByUser
类型并传递它即可。不要忘记使用 GC.KeepAlive
保留委托或将其存储在字段中,直到完成回调。
[DllImport("CppLibrary")]
private static extern void SetPointer(FunctionStorage func);
[DllImport("CppLibrary")]
private static extern void CallCppFunctionWithParam(ref StructCreatedByUser p1);
private delegate void FunctionStorage(ref StructCreatedByUser p1);
private static FunctionStorage _func = FunctionCreatedByUser; // need to keep this alive
public static void FunctionCreatedByUser(ref StructCreatedByUser data)
{
Console.WriteLine(data.x + " " + data.anything + " " + data.name );
}
static void Main()
{
StructCreatedByUser data = new StructCreatedByUser { x = 10, anything = 20.5f, name = "wedf" };
SetPointer(_func);
CallCppFunctionWithParam(ref data);
}