我有一个int func( int a, int* b)
需要在 Ada 95 中导入和使用的 C 函数。C 函数通常在 C 中调用为c = func(a, &b);
我一直将 C 函数导入 Ada,但一直避免使用通过引用参数传递的函数,但终于到了学习的时候了。
我想知道如何在 Ada 中声明这个函数,并且还想要一个简单的例子来使用它并显示声明的变量(因为我对 Access 类型仍然有点模糊)。
谢谢大家!
我有一个int func( int a, int* b)
需要在 Ada 95 中导入和使用的 C 函数。C 函数通常在 C 中调用为c = func(a, &b);
我一直将 C 函数导入 Ada,但一直避免使用通过引用参数传递的函数,但终于到了学习的时候了。
我想知道如何在 Ada 中声明这个函数,并且还想要一个简单的例子来使用它并显示声明的变量(因为我对 Access 类型仍然有点模糊)。
谢谢大家!
在 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;
您可以'Access
在aliased
变量上使用。只要您确定指针不会存储在 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 函数时的常见问题。
除了(和抄袭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