在 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;
您可以在aliased 变量上使用'Access。只要您确定指针不会存储在 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 代码将如何处理指针(就像您应该做的那样),您可以使用命名类型来指定不应传递对局部变量的引用。
注意事项 1: 如果您有一个过程(在 C 语言中:一个返回 void 的函数),您可以在您的 Ada 中使用 in out 指定一个要通过引用传递的变量过程声明而不是access。这样,您根本不需要担心访问类型。和之前一样,需要确保指针没有存放在C端。
注意事项 2: 无论如何,记录类型和数组都是通过引用传递的 - 除非您指定 pragma Convention (C_Pass_By_Copy, Your_Type);。这是在 Ada 中包装 C 函数时的常见问题。