Using ctypes to bind C functions returning pointers to get arrays

Hello!

I am learning ocaml during the past weeks, and now I would like to understand the use of ctypes creating by myself the binding (not using dune stanza at this moment). In particular, to use a C code to access specific information in binary files, but I am don’t know how to fill an OCaml array from a pointer (my level of C is also beginner)

To be specific:

In C, I will get first information about array size and type (I already implement these functions using ctypes).

/* called before several procedures to get nfvar integer and n, m values.*/
int data[n][m]
retrieval = get_array_int(nfvar,  &data[0][0])
/* the array data will have now the information of the binary file. */
/* In general the shape can be different, but known in advance */

In the case of Ocaml, I would have something like:

open Ctypes
open Foreign
let oget_array_int = foreign "get_array_int" (int @-> ptr int @-> returning int)

Now, I am lost about how to allocate an OCaml array of an specific type (here is Int) with the given dimensions to be filled by C code. If I understand well, I would define, a function that is using the previous oget_array_int. With other pointers (not arrays) of just an integer I was using Ctypes.allocate Ctypes.int. Maybe something similar to:

let readarray nfvar =
    let arr = Bigarray.(Array2.(create int) c_layout n m) in
              oget_array_int nfvar arr

In the book Read World OCaml I can’t find an specific example using Bigarray to begin with. Could I also deal with arrays of more than 3 dimensions?

Thank you!

1 Like

I’m learning myself, but I believe you will need to allocate memory for the second argument of the oget_array_int, and then you will need to copy that into an OCaml array. Don’t know if if that can be done directly.

let getArray nfvar n m = 
    let buff = allocate_n int ~count: n*m in
    let ret = oget_array_int nfvar buff in
   (* you probably want to check if ret is an error  *)
    Array.init nfvar (fun i -> !@(buff +@ i))

Something like this worked for me when trying to call proc_listpids in macos. Probably there are better alternatives that this !@(buff +@ i) pointer arithmetic syntax. This syntax makes me think I am missing something.

Also this doesn’t account for the two dimensions of the C array.

my 2 cents.

2 Likes

Thanks!

I think this is working with Array.int (n*m) (fun i -> !@(buff +!@ i) and probably for the several dimensions and I may simply reshape.

1 Like