How do I import a C-function to Ada with pass-by-reference arguments?
ada
Solution
In C, `int* b` can mean a lot of things. Perhaps it's really just a pointer to one variable, but it may also be an array for which `int a` is the length. This code assumes that `int* b` is actually just a value that's passed by reference:
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;
You can use `'Access` on `aliased` variables. This is safe as long as you're sure that the pointer won't be stored on the C side and accessed after the end of life of variable `B`. (If the C declaration uses the `const` keyword, you can use `access constant` on the Ada side, but that's Ada 2005 only.)
You can also use a named type:
-- ...
type Int_Access is access C.int;
function Func (A : C.int; B : Int_Access) return C.int;
-- ...
C := Func (A, B'Unchecked_Access);
-- ...
Now we need to use `'Unchecked_Access` because Ada normally does not allow a non-local access type (as `Int_Access`) to refer to a local variable. If you know what the C code will do with the pointer (like you should), you can use named types to specify that no references to local variables should be passed.
Nota bene 1: If you have a procedure (in C: a function that returns `void`), you can specify a variable to be passed by reference by using `in out` in your Ada procedure declaration instead of `access`. This way, you do not need to worry about access types at all. As before, you need to be sure that the pointer is not stored at the C side.
Nota bene 2: Record types and arrays are passed by reference anyway - unless you specify `pragma Convention (C_Pass_By_Copy, Your_Type);`. This is a common gotcha when wrapping C functions in Ada.
Problem
I have a C function `int func( int a, int* b)` that I need to import and use in Ada 95. Where the C function would typically be called in C as `c = func(a, &b);` I import C functions all the time into Ada, but have always avoided using functions with pass by reference arguments, but it's finally time to learn. I would like to know how to declare this function in Ada, and would also like a quick example of using it with declared variables shown (because I'm still a little fuzzy on the Access types). Thanks all!