在Ada-C绑定应用程序中映射结构成员的最佳实践

时间:2016-05-07 18:02:12

标签: c struct ada

在Ada-C绑定应用程序中,需要在C和Ada中定义的函数之间传递和读取/写入结构(记录),在C和Ada端声明结构符的最佳方法是什么,以确保正确映射两种语言之间的成员。举个例子,我在C中声明了一个结构(这里没有使用位字段),但是在Ada方面声明相同的结构(在Ada中记录)我还使用了 use 表示子句按位映射,然后使用Convention C pragma。我看到的是Ada没有正确地阅读这个结构,这可能是我认为可能因为成员的错误按位映射。

只是想知道什么是确保在Ada和C方面正确声明相同结构的最佳方法。应该在C侧,使用位字段声明结构,然后使用相同的位方案使用 use 表示子句在Ada端对相同的结构/记录进行十字转换?< / p>

例如C,

/* Position Data Structure */
typedef struct {
    float lat;
    float lon;
} POSITION_TYPE;

/* Fix Data Structure */
typedef struct {
    int32_t fix_id;
    char fix_type[20];
    char leg_type[7];
    char ident[8];
    char ident_code[11];
    char fix_descriptor[30];
    char way_ident[7];
    char ref_pt[8];
    char ref_pt_code[11];
    POSITION_TYPE position;
} FIX_DATA_TYPE;

我在Ada中声明了相同的结构:

  -- Position Record --------------------------------------------------------
  type Pos_Rec_Type is
    record
      Lat : C.C_float;
      Lon : C.C_float;
    end record;

    for Pos_Rec_Type use
      record
        Lat at 0 range  0..31;
        Lon at 0 range 32..63;
      end record;

   pragma Convention (Convention => C, Entity => Pos_Rec_Type);

  -- Fix Data Record --------------------------------------------------------
  type Fix_Data_Rec_Type is
    record
      Fix_Id              : C.int;
      Fix_Type            : C.char_array(1..20);
      Leg_Type            : C.char_array(1..7);
      Ident               : C.char_array(1..8);
      Ident_Code          : C.char_array(1..11);
      Fix_Desc            : C.char_array(1..30);
      Way_Ident           : C.char_array(1..7);
      Ref_Pt              : C.char_array(1..8);
      Ref_Pt_Code         : C.char_array(1..11);
      Position            : Pos_Rec_Type;
   end record;

    for Fix_Data_Rec_Type use
      record
        Fix_Id              at 0 range   0..31;
        Fix_Type            at 0 range  32..191;
        Leg_Type            at 0 range 192..247;
        Ident               at 0 range 248..311;
        Ident_Code          at 0 range 312..399;
        Fix_Desc            at 0 range 400..639;
        Way_Ident           at 0 range 640..695;
        Ref_Pt              at 0 range 696..759;
        Ref_Pt_Code         at 0 range 760..847;
        Position            at 0 range 848..911;
      end record;

   pragma Convention (Convention => C, Entity => Fix_Data_Rec_Type);

但是当我在Ada一侧填充这个结构并将其转移到C函数时,我看到位置记录没有被正确解码。当我禁用 Fix_Data_Rec_Type 的representation子句时,它工作正常。

1 个答案:

答案 0 :(得分:3)

如果您使用-gnatR打印类型的表示信息,您将找到

with rep子句:

for Pos_Rec_Type'Size use 64;
for Pos_Rec_Type'Alignment use 4;
for Pos_Rec_Type use record
   Lat at 0 range  0 .. 31;
   Lon at 4 range  0 .. 31;
end record;

for Fix_Data_Rec_Type'Object_Size use 928;
for Fix_Data_Rec_Type'Value_Size use 912;
for Fix_Data_Rec_Type'Alignment use 4;
for Fix_Data_Rec_Type use record
   Fix_Id      at   0 range  0 .. 31;
   Fix_Type    at   4 range  0 .. 159;
   Leg_Type    at  24 range  0 .. 55;
   Ident       at  31 range  0 .. 63;
   Ident_Code  at  39 range  0 .. 87;
   Fix_Desc    at  50 range  0 .. 239;
   Way_Ident   at  80 range  0 .. 55;
   Ref_Pt      at  87 range  0 .. 63;
   Ref_Pt_Code at  95 range  0 .. 87;
   Position    at 106 range  0 .. 63;
end record;

没有rep子句:

for Pos_Rec_Type'Size use 64;
for Pos_Rec_Type'Alignment use 4;
for Pos_Rec_Type use record
   Lat at 0 range  0 .. 31;
   Lon at 4 range  0 .. 31;
end record;

for Fix_Data_Rec_Type'Size use 928;
for Fix_Data_Rec_Type'Alignment use 4;
for Fix_Data_Rec_Type use record
   Fix_Id      at   0 range  0 .. 31;
   Fix_Type    at   4 range  0 .. 159;
   Leg_Type    at  24 range  0 .. 55;
   Ident       at  31 range  0 .. 63;
   Ident_Code  at  39 range  0 .. 87;
   Fix_Desc    at  50 range  0 .. 239;
   Way_Ident   at  80 range  0 .. 55;
   Ref_Pt      at  87 range  0 .. 63;
   Ref_Pt_Code at  95 range  0 .. 87;
   Position    at 108 range  0 .. 63;
end record;

使用rep子句,Position组件实际上未对齐(106不能被4整除)。