C#如何正确读取C++函数返回的指针类型结构体的值?
问题根因
你当前的C++代码存在经典的野指针问题:get_xy_ptr中定义的XY p是栈分配的局部变量,函数执行结束后对应的栈帧会被系统回收,返回的&p指向的内存区域会被后续操作覆盖,内容无效,因此C#侧读取到的是乱值/0值。
解决方案
要解决该问题同时兼容WebAssembly的指针返回要求,需要将结构体分配到堆上手动管理生命周期,同时配套内存释放逻辑避免泄漏,修改后的代码如下:
C++侧修改代码
#define E __declspec( dllexport ) struct XY { int x, y; }; extern "C" { E XY* get_xy_ptr() { // 改为堆分配,生命周期手动管理,不会随函数返回被自动释放 XY* p = new XY(); p->x = 15; p->y = 23; return p; } // 配套导出内存释放函数,避免内存泄漏 E void free_xy_ptr(XY* ptr) { if (ptr != nullptr) { delete ptr; } } }
如果你偏好C风格内存管理,把
new/delete替换为malloc/free效果完全一致,同样兼容Emscripten编译要求。
C#侧修改代码
// 显式指定结构体布局和C++侧保持一致,避免C#自动调整布局导致内存偏移 [StructLayout(LayoutKind.Sequential)] record struct XY(int x, int y); // 导入C++导出函数 [DllImport("CppLibrary.dll")] static extern IntPtr get_xy_ptr(); [DllImport("CppLibrary.dll")] static extern void free_xy_ptr(IntPtr ptr); IntPtr pointer = get_xy_ptr(); XY xy = Marshal.PtrToStructure<XY>(pointer); Console.WriteLine("xy.x : {0}", xy.x); // 正常输出15 Console.WriteLine("xy.y : {0}", xy.y); // 正常输出23 // 内存使用完成后手动调用释放函数,避免内存泄漏 free_xy_ptr(pointer);
注意事项
- 禁止返回栈内存的指针,该问题属于C/C++通用错误,和跨语言互操作本身无关
- 手动分配的堆内存必须配套对应的释放逻辑,否则会出现内存泄漏,长时间运行会导致内存占用过高
- 若后续结构体复杂度提升(包含字符串、数组、指针成员等),需要额外显式指定结构体布局对齐规则,保证C++和C#侧内存布局完全一致
- 这套堆分配+指针返回的写法完全符合Emscripten的WebAssembly编译要求,Wasm的线性内存模型完全支持手动分配的堆指针传递,不会出现兼容问题
内容的提问来源于stack exchange,提问作者Sith2021
相关产品推荐
相关产品推荐

