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

.NET Framework4.8 PInvoke调用返回结构体C函数提示类型签名不兼容

问题解答

对应代码片段

C 端 DLL 代码

const int SIZE = 5;

typedef struct Foo{
    uint8_t data[SIZE];
} Foo;

DLL_EXPORT Foo bar(){
    Foo f;
    //fill f
    return f;
}

C# 端互操作定义

struct Foo{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    byte[] data;
}

[DllImport(...)]
static extern Foo bar();

不同版本.NET运行表现差异原因

  • .NET Framework 4.8的P/Invoke编组器存在原生限制:不支持非blittable值类型作为P/Invoke的返回值。你定义的Foo结构体中包含标记了[MarshalAs]特性的数组成员,不属于可直接内存拷贝的blittable类型,因此会抛出Method's type signature is not PInvoke compatible异常。
  • .NET Core 3.0及后续版本(包括.NET 5.0+)对P/Invoke编组器做了大量功能扩展,新增了非blittable结构体作为返回值的编组支持,因此这段代码可以在.NET 5.0环境下正常运行。

内存安全风险说明

不存在访问已释放内存的风险,原因如下:

  • C端bar函数采用值返回的方式返回结构体,C语言规范中,值返回结构体时会将整个结构体的完整内容拷贝到调用方的栈上下文空间,不会返回指向函数栈内存的指针,函数返回后栈回收不会影响已经完成拷贝的结构体数据。
  • C#侧P/Invoke编组过程中,会将C端返回的结构体数据完整拷贝到托管内存中的Foo实例,其中的data数组成员会被编组为独立的托管数组,和C DLL的原生内存空间完全独立,后续访问不会涉及到原生侧已经释放的栈内存。

内容的提问来源于stack exchange,提问作者elo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:57:01