首页 文章

从Ada访问c常量

提问于
浏览
4

我有一个头文件,其类型定义如下

#ifndef SETSIZE
   #define SETSIZE 32
#endif

typedef struct _set {
    unsigned  array[SETSIZE];
} set_t;

要使用相应的C函数,我需要在Ada中使用set_t类型 . 问题是SETSIZE是一个可配置的参数(默认值为32) . 如果我理解正确,我无法访问Ada的预处理器定义 . 是否可以在c文件中添加一个常量并在Ada中使用它,如下所示:

#ifndef SETSIZE
   #define SETSIZE 32
#endif

const size_t test = SETSIZE;
// Alternative
enum { test2 = SETSIZE };

--Ada--
-- import test somehow
type set_array is array (0 .. test) of aliased Interfaces.C.unsigned;
type set_t is record
  array_field : aliased set_array;
end record;

或者在Ada中正确使用此类型的任何其他方式,而无需在原始C代码中进行太多更改

2 回答

  • 7

    为什么不简单:

    SetSize: constant Interfaces.C.Size_T;
    pragma Import(
        Convention    => C,
        Entity        => SetSize,
        External_Name => "set_size" 
    );
    

    在你的 C 文件中:

    const size_t set_size = SETSIZE;
    

    测试 gnatmake 4.8.1

    // File: set_def.c
    #include <stdlib.h>
    
    #ifndef SETSIZE
       #define SETSIZE 32
    #endif
    
    const size_t set_size = SETSIZE ;
    
    typedef struct _set {
        unsigned  array[SETSIZE];
    } set_t;
    

    编译 set_def.c

    Z:\> gcc -c set_def.c
    
    -- File: main.adb
    with Interfaces.C, Ada.Text_IO, Ada.Integer_Text_IO ;
    
    procedure Main is
    
        use type Interfaces.C.Size_T ; -- To have access to the - operator
    
        SetSize: constant Interfaces.C.Size_T;
    
        pragma Import (
            Convention    => C,
            Entity        => SetSize,
            External_Name => "set_size" 
        );
    
        -- Note that you should go to SetSize - 1
        type Set_Array is array(0 .. SetSize - 1) of aliased Interfaces.C.Unsigned;
        type Set_T is
          record
            Array_Field: aliased Set_Array;
          end record;
    
        MySet: Set_T := (Array_Field => (1, 2, 3, others => 0)); 
    
    begin
       Ada.Integer_Text_IO.Put (Integer(SetSize), 0); Ada.Text_IO.New_Line;
       Ada.Integer_Text_IO.Put (MySet.Array_Field'Length, 0); Ada.Text_IO.New_Line;
       for I in MySet.Array_Field'range loop
           Ada.Integer_Text_IO.Put (Integer(MySet.Array_Field(I)), 0);
           Ada.Text_IO.Put(' ');
       end loop;
    end Main;
    

    编译 main.adb 并与 set_def.o 链接:

    Z:\> gnatmake main.adb -largs set_def.o
    Z:\> main.exe
    32
    32
    1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    
  • 4

    在类似的情况下,我所做的是添加一个从Ada导入的函数:

    size_t getsize(void) {
       return SETSIZE;
    }
    

    而在Ada方面:

    function Getsize return Interfaces.C.size_t;
    pragma Import(C, Getsize); -- From memory, this pragma is probably somewhat wrong
    

    如果你不想重复调用这个函数,对于(可以忽略不计的话)开销,你可以在函数定义之后:

    Setsize : constant Interfaces.C.size_t := Getsize;
    -- Or convert to any more convenient type at this point.
    

    我猜你也可以用变量做同样的事情 .

相关问题