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!
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With