В 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
, вы можете использовать access constant
на стороне Ады, но это только для Ады 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
, потому что Ада обычно не позволяет нелокальному типу доступа (как Int_Access
) ссылаться на локальную переменную. Если вы знаете, что код C будет делать с указателем (а вы должны), вы можете использовать именованные типы, чтобы указать, что ссылки на локальные переменные не должны передаваться.
Примечание 1: если у вас есть процедура (в C: функция, которая возвращает void
), вы можете указать переменную, которая будет передаваться по ссылке, используя in out
в объявлении процедуры Ada вместо access
. Таким образом, вам вообще не нужно беспокоиться о типах доступа. Как и раньше, вы должны быть уверены, что указатель не хранится на стороне C.
Примечание 2. Типы записей и массивы в любом случае передаются по ссылке, если только вы не укажете pragma Convention (C_Pass_By_Copy, Your_Type);
. Это обычная ошибка при переносе функций C в Ada.
person
flyx
schedule
25.06.2012