我有一个C函数int func( int a, int* b)
我需要在Ada 95中导入和使用。其中C函数通常在C中被调用为c = func(a, &b);
我一直将C函数导入Ada,但总是避免使用带引用参数的函数,但最后还是要学习。
我想知道如何在Ada中声明这个函数,并且还想要一个快速示例,将它与显示的声明变量一起使用(因为我对Access类型仍然有点模糊)。
全部谢谢!
答案 0 :(得分:8)
在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端并在变量B
的生命周期结束后访问,这是安全的。 (如果C声明使用const
关键字,您可以在Ada端使用access constant
,但这只是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通常不允许非本地访问类型(如Int_Access
)引用局部变量。如果你知道C代码将用指针做什么(就像你应该这样),你可以使用命名类型来指定不应该传递对局部变量的引用。
Nota bene 1:如果你有一个程序(在C中:一个返回void
的函数),你可以使用{{1}指定一个通过引用传递的变量在你的Ada程序声明中而不是in out
。这样,您根本不需要担心访问类型。和以前一样,你需要确保指针没有存储在C端。
Nota bene 2:记录类型和数组无论如何都是通过引用传递的 - 除非您指定access
。在Ada中包装C函数时,这是一个常见的问题。
答案 1 :(得分: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