将结构从 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 时,我想知道:

  1. 如果我在 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"!

  2. 还有其他(更好的)方法可以通过引用传递调用吗?我相信我可以将它作为 "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 编译器兼容)

关于您的问题:

  1. 这样可以,但为什么要乱用指针呢?

  2. 不,那行不通,Ada 中的访问类型(和访问值)不是地址。将 System.Address 转换为访问值需要 System.Address_To_Access_Conversions,但同样,为什么要乱用指针?