You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:24:03