5

我有一个int func( int a, int* b)需要在 Ada 95 中导入和使用的 C 函数。C 函数通常在 C 中调用为c = func(a, &b);

我一直将 C 函数导入 Ada,但一直避免使用通过引用参数传递的函数,但终于到了学习的时候了。

我想知道如何在 Ada 中声明这个函数,并且还想要一个简单的例子来使用它并显示声明的变量(因为我对 Access 类型仍然有点模糊)。

谢谢大家!

4

2 回答 2

9

在 C 中,int* b可能意味着很多事情。也许它实际上只是一个指向一个变量的指针,但它也可能是一个int a长度为数组的数组。此代码假定它int* b实际上只是一个通过引用传递的值:

with Interfaces.C;

-- ...
package C renames Interfaces.C;

function Func (A : C.int; B : access C.int) return C.int;
pragma Import (Convention => C, Entity => Func,
               External_Name => "func");

-- ...

declare
   A : C.int := 42;
   B : aliased C.int := 23;
   C : C.int;
begin
   C := Func (A, B'Access);
   -- ...
end;

您可以'Accessaliased变量上使用。只要您确定指针不会存储在 C 端并在 variable 生命周期结束后访问,这是安全的B。(如果 C 声明使用const关键字,您可以access constant在 Ada 端使用,但仅适用于 Ada 2005。)

您还可以使用命名类型:

-- ...
type Int_Access is access C.int;
function Func (A : C.int; B : Int_Access) return C.int;
-- ...
C := Func (A, B'Unchecked_Access);
-- ...

现在我们需要使用'Unchecked_Access,因为 Ada 通常不允许非本地访问类型(as Int_Access)引用局部变量。如果您知道 C 代码将如何处理指针(就像您应该做的那样),您可以使用命名类型来指定不应传递对局部变量的引用。

注意事项 1:如果您有一个过程(在 C 中:一个返回 的函数void),您可以通过in out在 Ada 过程声明中使用而不是access. 这样,您根本不需要担心访问类型。和以前一样,您需要确保指针没有存储在 C 端。

注意事项 2:记录类型和数组无论如何都是通过引用传递的 - 除非您指定pragma Convention (C_Pass_By_Copy, Your_Type);. 这是在 Ada 中包装 C 函数时的常见问题。

于 2012-06-25T14:22:16.723 回答
4

除了(和抄袭flyx)之外,我还提供了一个完整的解决方案:

文件 c_thing.c

#include <stdio.h>

int foo (int a, int * b) {
  printf ("A:%d, B %d\n",a, *b);
}

文件 ada_main.adb

with Interfaces.C;

procedure Ada_Main is 

   package C renames Interfaces.C;

   function Func (A : C.int; B : access C.int) return C.int;
   pragma Import (Convention => C, Entity => Func,
                  External_Name => "foo");

   A : C.int := 42;
   B : aliased C.int := 23;
   R : C.int;

begin

   R := Func (A, B'Access);

end Ada_Main;

编译(Linux):

gcc -c c_thing.c
gnatmake -c ada_main.adb
gnatbind ada_main.ali
gnatlink ada_main.ali c_thing.o

跑步

./ada_main 
A:42, B 23
于 2012-06-25T20:40:54.923 回答