如何从C#调用带引用参数的C++函数?代码方案验证问询
能否通过给定C#代码调用C++函数并获取正确的min.x值?
C++ 原代码
struct Vector3f { float x; float y; float z; }; void getLocalBounds(BoxShape* boxShape, Vector3f& min, Vector3f& max) { min.x = 3; }
请问是否可以通过如下C#代码调用上述C++函数,并获取到min.x的值为3?
C# 调用代码
[StructLayout(LayoutKind.Sequential)] public struct Vector3f { public float x; public float y; public float z; } [DllImport("a.lib", EntryPoint = "getLocalBounds", CallingConvention = CallingConvention.Cdecl)] public static void getLocalBounds(IntPtr boxShapePtr, ref Vector3f min, ref Vector3f max); public void Test() { IntPtr boxShapePtr = null; // 假设已正确构造有效指针 Vector3f a, b; a.x = 100; getLocalBounds(boxShapePtr, ref a, ref b); Assert(a.x == 3); // 假设C++函数已赋值a.x }
注:Vector3f getBoundMin();这种方式可行,但它是基于栈传值而非栈传引用。
可以实现,但需要满足几个关键前提:
- 修正DllImport的库路径:C#的
DllImport不能直接引用.lib静态库,Windows下需改为a.dll,Linux/macOS下改为liba.so/liba.dylib,同时要确保C++代码已编译为对应的动态链接库 - 保证结构体内存布局一致:C#中
Vector3f标注了[StructLayout(LayoutKind.Sequential)],和C++结构体的默认顺序布局完全匹配,三个float成员的内存排列、大小都一致,这是数据正确传递的基础 - 匹配调用约定:C++函数在GCC编译器下默认使用
cdecl调用约定,C#代码中指定了CallingConvention.Cdecl,两者匹配才能保证参数栈的正确处理 - 确保函数导出名称正确:如果C函数没有添加
extern "C"修饰,编译后会被C名字修饰,此时EntryPoint指定的getLocalBounds会找不到函数。需要给C++函数加上extern "C"来导出原始名称:extern "C" void getLocalBounds(BoxShape* boxShape, Vector3f& min, Vector3f& max) { min.x = 3; }
当以上条件都满足时,C#中通过ref传递Vector3f结构体,对应C的引用传递(本质都是传递内存地址),C函数修改min.x的操作会直接作用到C#变量a的内存上,Assert(a.x == 3)会成立。
内容的提问来源于stack exchange,提问作者216 dark
相关产品推荐
相关产品推荐

