【问题标题】:Access c constant from Ada从 Ada 访问 c 常量
【发布时间】:2018-10-26 23:17:33
【问题描述】:

我有一个这样的类型定义的头文件

#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 代码进行太多更改

【问题讨论】:

标签: c ada


【解决方案1】:

为什么不简单:

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

【讨论】:

  • 这看起来像我正在寻找的东西。因为 SetSize 是一个常量,所以应该可以使用它来定义数组。看起来很棒。当我回到办公桌前时,我会试试看。
【解决方案2】:

在类似的情况下,我所做的是添加一个从 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.

我猜你也可以对变量做同样的事情。

【讨论】:

  • Ada 阐述的一个很好的附属品是,您可以将 Ada 中的 C 常量用于可变大小的事物,而不必依赖预定义的最大大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 2015-11-04
  • 2011-11-27
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多