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

使用[UnmanagedCallersOnly]返回结构体时遇__cdecl语法编译错误

问题解决:返回结构体时cl.exe编译报错的修复方案

核心问题原因

返回自定义结构体时编译报错,本质是C#结构体内存布局未明确、调用约定不匹配,导致DNNE生成的C++包装代码出现语法错误,触发cl.exe返回代码2。

具体修复步骤

1. 给C#结构体添加显式内存布局属性

Delphi和C#的结构体内存布局必须严格一致,否则不仅编译会出问题,运行时也会出现数据错乱。给ReturnTest结构体添加StructLayout属性:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ReturnTest
{
    public int code;
    public IntPtr txt;
}
  • LayoutKind.Sequential保证成员按声明顺序排列,和Delphi的record默认布局一致
  • CharSet.Unicode匹配BSTR的Unicode编码格式

2. 给导出函数显式指定调用约定

[UnmanagedCallersOnly]默认调用约定为Cdecl,但需要显式声明避免DNNE生成代码时出现歧义:

[UnmanagedCallersOnly(CallingConvention = CallingConvention.Cdecl)]
public static ReturnTest TestFunction()
{
    ReturnTest returnTest = new ReturnTest();
    returnTest.code = 1337;
    returnTest.txt = Marshal.StringToBSTR("a b c d q ¥ K xyz");
    return returnTest;
}

如果Delphi端使用stdcall调用约定,只需把CallingConvention.Cdecl改成CallingConvention.StdCall即可。

3. 确保DNNE配置正确

  • 确认项目目标框架为.NET 5或更高版本([UnmanagedCallersOnly]从.NET 5开始支持)
  • 检查DNNE生成的C++包装文件,确保结构体声明位于函数之前,且调用约定语法正确(比如__cdecl修饰符位置正确)

4. Delphi端匹配结构体定义

Delphi端必须定义和C#完全一致的record,同时注意BSTR的内存释放:

type
  ReturnTest = record
    code: Integer;
    txt: PWideChar;
  end;

// 调用示例
procedure CallTestFunction;
var
  Result: ReturnTest;
  S: WideString;
begin
  Result := TestFunction;
  S := Result.txt;
  SysFreeString(Result.txt); // 必须释放BSTR,避免内存泄漏
end;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:46:07