I finally got it working using the package Interface.C.Pointers, it is quite easy, here is the code :
with Interfaces.C, Interfaces.C.Pointers ; use Interfaces.C ; with Ada.Text_IO ; -- To Check procedure MYRECTest is package IIO is new Ada.Text_IO.Integer_IO (Int) ; type PChar is access all Char ; type MYREC is record N : Int ; Str : PChar ; end record ; pragma Convention(C, MYREC); DefaultMyrec : MYREC := (0, null) ; type MYREC_Array is array (Int range <>) of aliased MYREC ; pragma Convention(C, MYREC_Array); -- Not sure if useful... -- Here is the trick package PMYREC is new Interfaces.C.Pointers (Int, MYREC, MYREC_Array, DefaultMyrec) ; function AllocMyrec (N : in Int) return PMYREC.Pointer ; pragma Import (C, AllocMyrec, "allocMyrec"); P : PMYREC.Pointer := AllocMyrec(5) ; StartP : PMYREC.Pointer := P ; -- Initial pointer A : MYREC_Array(0..4) := PMYREC.Value(P, 5) ; -- Here is a copy begin for I in A'Range loop -- Real access: IIO.Put(P.all.N) ; P.all.N := P.all.N + 3 ; -- Here you're really accessing the allocated memory, not just a copy PMYREC.Increment(P) ; -- 'Fake' access: IIO.Put(A(I).N) ; A(I).N := A(I).N + 3 ; -- Here you're accessing a copy, so the modification is not made on the allocated memory end loop ; Ada.Text_IO.New_Line ; end MYRECTest ;
I tested the above code setting the n attribute of all _MYREC elements in the C function to 42 + i and printing it in the Ada body, it worked (I got 42, 43, 44, 45, 46). The C function looked like (for test) :
typedef struct _MYREC { int n ; char *str ; } MYREC ; MYREC * allocMyrec (int n) { MYREC *res = malloc(n * sizeof(MYREC)) ; int i ; for (i = 0 ; i < n ; i++) { res[i].n = 42 + i; } return res ; }
The DefaultMyrec variable is useless but necessary for the package creation. I assumed you always use the Value function with the length parameter to retrieve value.
More information about the package : http://www.adaic.org/resources/add_content/standards/05rm/html/RM-B-3-2.html
EDIT: The original code was making a copy of the memory pointed by P so if you update anything in the array A it won't be change in the memory allocated. In fact you should directly use the pointer P like shown in the edited code.
EDIT: I used a 'stupid' access all Char for the str attribute of MYREC but you can (and should) use almost the same stuff from Interfaces.C.Pointers if necessary. I tested it but did not want to put it in the answer because it did not add anything to it.
allocMyRecfunction, or do you want Ada code that just does something similar without calling the C function?allocMyRecbut I want to work with ADA on aMYREC_Array