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对结构体成员的读写。
编译与测试
- 重新编译Ada动态链接库:
gprbuild -P ./math.gpr -p
- 编译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
相关产品推荐
相关产品推荐

