Passing structure from C to Ada

心不动则不痛 提交于 2020-01-23 18:17:12

问题


I need to pass a structure from C to Ada in an Ada binding application. Thus, I have declared the structure in both Ada and C so that both the source sides can decipher the structure composition.

In C,

typedef struct {
   int Status_Code;
   int Error_Code;
} Edit_Result_Type;

In Ada,

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;

When I am passing the structure from C to Ada through call by reference, I wanted to know:

  1. Is it ok if I declare an "access all" vector type for the structure (as done above - Edit_Result_Rec_Type_Ptr) in Ada and use it directly as a formal parameter in Ada function. For Eg:

    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;
    

    Is this approach FATAL? I know it is, just wanted to know "how" in depth!

  2. Any other (better) approaches for passing through call by reference? I believe I can pass it as a "System.Address" parameter and do an "unchecked conversion" into Edit_Result_Rec_Type_Ptr in a local vector inside the Ada function and then read/write record members? Does this approach has any fatalities?


回答1:


When interfacing Ada and C, you should really read the RM, Annex B.3, which says:

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.

So, in your procedure, just do:

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;

and

pragma Export(C, Process_Data);

(or use the aspect, if Ada 2012)

That being said, you shouldn't use Integer in your record definition, Interfaces.C.int is the way to go:

type Edit_Result_Rec_Type is
   record
      Status     : Interfaces.C.int;
      Error_Code : Interfaces.C.int;
   end record;

which will match the C int on your platform (assuming your C compiler is compatible with the Ada compiler)

As for your questions:

  1. That would work, but why mess around with pointers?

  2. No, that wouldn't work, access types (and access values) in Ada are not addresses. Converting a System.Address to an access value requires System.Address_To_Access_Conversions, but again, why mess around with pointers?



来源:https://stackoverflow.com/questions/36227946/passing-structure-from-c-to-ada

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!