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

Ada与C通过DLL传递复杂类型(如结构体)的问题排查

Ada与C交互时结构体类型不匹配的问题解决

问题根源

你的代码核心问题在于Ada原生String类型和C的char[]内存布局不兼容。Ada的String即使是固定长度,内部也隐含长度相关的结构信息,而C的字符数组是纯粹的连续字节序列,直接映射会导致数据传递时内存错位,最终使得修改后的Age值无法正确返回。

解决方案

需要将Ada结构体中的String替换为Interfaces.C.Char_Array,并确保结构体遵循C的内存约定,具体修改如下:

1. 修改Ada包规范(person.ads)

with Interfaces.C; use Interfaces.C;

package Person is

   type Person_Record is record
      Name    : Char_Array(1 .. 100);  -- 对应C的char[101],预留终止符位置
      Age     : int;
      Address : Char_Array(1 .. 100);
   end record with Convention => C;  -- 强制使用C的内存布局规则

   function Set_Age_To_Five(P : Person_Record) return Person_Record;
   pragma Export (C, Set_Age_To_Five, "Set_Age_To_Five");

end Person;

2. 修改Ada包体(person.adb)

with Interfaces.C; use Interfaces.C;

package body Person is

   function Set_Age_To_Five(P : Person_Record) return Person_Record is
      Result : Person_Record := P;
   begin
      Result.Age := 5;
      return Result;
   end Set_Age_To_Five;

end Person;

3. 保持C代码和头文件不变

你的C头文件math.h和主程序代码无需修改,因为char[101]的前100个字节刚好对应Ada中Char_Array(1..100)的内容,C中snprintf自动添加的字符串终止符会存在第101位,不影响Ada对结构体成员的读写。

编译与测试

  1. 重新编译Ada动态链接库:
gprbuild -P ./math.gpr -p
  1. 编译C代码并链接生成的DLL,运行后即可得到预期输出:
Name: John
Age: 5
Address: 123 Main St

补充说明

  • 使用Convention => C可以确保Ada结构体的成员顺序、对齐方式完全和C一致,避免跨语言交互时的内存解析错误。
  • 如果需要在Ada中处理字符串的终止符,可以借助Interfaces.C.Strings包中的To_Ada、To_C函数进行Ada字符串和C字符数组的转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:24:58