将结构从 C 传递给 Ada
Passing structure from C to Ada
我需要在 Ada 绑定应用程序中将结构从 C 传递到 Ada。因此,我在 Ada 和 C 中都声明了结构,以便源代码双方都可以破译结构组成。
在 C 中,
typedef struct {
int Status_Code;
int Error_Code;
} Edit_Result_Type;
在阿达,
type Edit_Result_Rec_Type is
record
Status : Integer;
Error_Code : Integer;
end record;
pragma Convention (Convention => C,
Entity => Edit_Result_Rec_Type);
for Edit_Result_Rec_Type use
record
Status at 0 range 0 .. 31;
Error_Code at 0 range 32 .. 63;
end record;
type Edit_Result_Rec_Type_Ptr is access all Edit_Result_Rec_Type;
当我通过引用调用将结构从 C 传递给 Ada 时,我想知道:
如果我在 Ada 中为结构声明一个 "access all" 向量类型(如上所述 - Edit_Result_Rec_Type_Ptr
)并直接将其用作 Ada 中的形式参数,是否可以?功能。例如:
procedure Process_Data (Edit_Result_Ptr : in out Edit_Result_Rec_Type_Ptr) is
begin
Edit_Result_Ptr.Status := 1;
Edit_Result_Ptr.Error_Code := 0;
end Process_Data;
这种方法是致命的吗?我知道是,只是想深入了解"how"!
还有其他(更好的)方法可以通过引用传递调用吗?我相信我可以将它作为 "System.Address" 参数传递,并在 Ada 函数内的局部向量中将 "unchecked conversion" 执行到 Edit_Result_Rec_Type_Ptr
,然后 read/write 记录成员?这种方法会导致死亡吗?
连接 Ada 和 C 时,您应该真正阅读 RM,附件 B.3,其中说:
An Ada parameter of a record type T, of any mode, other than an in parameter of a type of convention C_Pass_By_Copy, is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T.
因此,在您的程序中,只需执行以下操作:
procedure Process_Data (Edit_Result : in out Edit_Result_Rec_Type) is
begin
Edit_Result.Status := 1;
Edit_Result.Error_Code := 0;
end Process_Data;
和
pragma Export(C, Process_Data);
(或使用方面,如果 Ada 2012)
也就是说,您不应该在记录定义中使用 Integer,Interfaces.C.int 是正确的选择:
type Edit_Result_Rec_Type is
record
Status : Interfaces.C.int;
Error_Code : Interfaces.C.int;
end record;
这将匹配您平台上的 C int(假设您的 C 编译器与 Ada 编译器兼容)
关于您的问题:
这样可以,但为什么要乱用指针呢?
不,那行不通,Ada 中的访问类型(和访问值)不是地址。将 System.Address
转换为访问值需要 System.Address_To_Access_Conversions
,但同样,为什么要乱用指针?
我需要在 Ada 绑定应用程序中将结构从 C 传递到 Ada。因此,我在 Ada 和 C 中都声明了结构,以便源代码双方都可以破译结构组成。
在 C 中,
typedef struct {
int Status_Code;
int Error_Code;
} Edit_Result_Type;
在阿达,
type Edit_Result_Rec_Type is
record
Status : Integer;
Error_Code : Integer;
end record;
pragma Convention (Convention => C,
Entity => Edit_Result_Rec_Type);
for Edit_Result_Rec_Type use
record
Status at 0 range 0 .. 31;
Error_Code at 0 range 32 .. 63;
end record;
type Edit_Result_Rec_Type_Ptr is access all Edit_Result_Rec_Type;
当我通过引用调用将结构从 C 传递给 Ada 时,我想知道:
如果我在 Ada 中为结构声明一个 "access all" 向量类型(如上所述 -
Edit_Result_Rec_Type_Ptr
)并直接将其用作 Ada 中的形式参数,是否可以?功能。例如:procedure Process_Data (Edit_Result_Ptr : in out Edit_Result_Rec_Type_Ptr) is begin Edit_Result_Ptr.Status := 1; Edit_Result_Ptr.Error_Code := 0; end Process_Data;
这种方法是致命的吗?我知道是,只是想深入了解"how"!
还有其他(更好的)方法可以通过引用传递调用吗?我相信我可以将它作为 "System.Address" 参数传递,并在 Ada 函数内的局部向量中将 "unchecked conversion" 执行到
Edit_Result_Rec_Type_Ptr
,然后 read/write 记录成员?这种方法会导致死亡吗?
连接 Ada 和 C 时,您应该真正阅读 RM,附件 B.3,其中说:
An Ada parameter of a record type T, of any mode, other than an in parameter of a type of convention C_Pass_By_Copy, is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T.
因此,在您的程序中,只需执行以下操作:
procedure Process_Data (Edit_Result : in out Edit_Result_Rec_Type) is
begin
Edit_Result.Status := 1;
Edit_Result.Error_Code := 0;
end Process_Data;
和
pragma Export(C, Process_Data);
(或使用方面,如果 Ada 2012)
也就是说,您不应该在记录定义中使用 Integer,Interfaces.C.int 是正确的选择:
type Edit_Result_Rec_Type is
record
Status : Interfaces.C.int;
Error_Code : Interfaces.C.int;
end record;
这将匹配您平台上的 C int(假设您的 C 编译器与 Ada 编译器兼容)
关于您的问题:
这样可以,但为什么要乱用指针呢?
不,那行不通,Ada 中的访问类型(和访问值)不是地址。将
System.Address
转换为访问值需要System.Address_To_Access_Conversions
,但同样,为什么要乱用指针?