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

Delphi DLL返回结构体在C# P/Invoke调用出现兼容性异常问题排查

Delphi DLL返回结构体的C# PInvoke兼容问题解决

核心错误原因

Delphi的stdcall函数返回大于4字节的结构体时,会遵循Win32调用约定的特殊规则:将结构体作为隐藏指针参数传递(函数内部把数据写入该指针指向的内存),而非直接返回结构体。C#直接声明返回Settings类型的写法,无法匹配这种底层调用逻辑,这是触发MarshalDirectiveException的根本原因。

另外你的C#结构体还有两处语法错误:

  • 结构体字段不能直接初始化(int[] Angles = new int[21];属于非法写法),只能声明字段。
  • 构造函数名称与结构体名称不匹配(Laser_Settings()应改为Settings())。

修正后的C#代码

1. 正确的结构体定义

[StructLayout(LayoutKind.Sequential)]
public struct Settings
{
    public int Error;
    public int NumOfAngles;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
    public int[] Angles;
    public int Version;

    // 可选:通过构造函数初始化数组,避免空引用
    public Settings(bool initializeArray)
    {
        Error = 0;
        NumOfAngles = 0;
        Version = 0;
        Angles = initializeArray ? new int[21] : null;
    }
}

注意:字段必须设为public,否则PInvoke无法访问内存中的结构体数据;去掉字段的直接赋值逻辑,改用构造函数可选初始化数组。

2. 修正后的DllImport声明

将返回值改为void,通过out参数接收结构体数据:

[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern void GetSettings(out Settings settings);

3. 调用代码

// 初始化结构体并分配数组内存
var settings = new Settings(true);
DelphiWrapper.GetSettings(out settings);

补充说明

  • Delphi的integer和C#的int均为32位整数,类型匹配正确。
  • LayoutKind.Sequential保证结构体字段顺序与Delphi的record完全一致,必须保留。
  • UnmanagedType.ByValArray, SizeConst = 21与Delphi的array[1..21] of integer长度完全匹配,无需调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:35