I want to return int-arrays from a C-library to a OCaml program. In order to do so, I thought I'd just wrap them in a Bigarray.Array1.t. Below is a small demo of the C-stubs:
/* nativeintarray.c */ 
#include <stdio.h>
#include <assert.h>
#include <caml/memory.h>
#include <caml/bigarray.h>
CAMLprim value make_array(value unit) {
  CAMLparam1(unit);
  int* a = calloc (1, sizeof(int));
  a[0] = -1;
  /* Create a C-style bigarray, yes it is a memory leak */
  CAMLreturn(caml_ba_alloc_dims(CAML_BA_NATIVE_INT | CAML_BA_C_LAYOUT, 1, a, 1));
}
My example program looks like this:
(* nativeintarray.ml *)
open Bigarray
(** Type for int arrays from/to C *)
type ivector = (nativeint, nativeint_elt, c_layout) Array1.t
external make_array : unit -> ivector = "make_array"
let () =
  Printf.printf "%nd\n" (make_array ()).{0}
Since nativeint is a signed integer, I expect the program to output -1, instead it gives:
% ocamlbuild nativeintarray_c.o                                        
Finished, 1 target (0 cached) in 00:00:00.
% ocamlbuild -package bigarray -lflags nativeintarray_c.o nativeintarray.native
Finished, 4 targets (0 cached) in 00:00:00.
% ./nativeintarray.native 
4294967295
As I said, I naively expected nativeint to match the int in my local C-compiler, but this is obviously not the case. Can somebody explain this? 
Platform: Ocaml 4.02.3, gcc 6.1.1, all 64 bit
Have you checked sizeof(int) is really 8 in your environment?  
In Win64, OCaml 4.03.0 with x86_64-w64-mingw32-gcc (MinGW64 compiler of Cygwin), your code runs just you have described (prints 4294967295, instead of -1).  There, sizeof(int) does not return 8 but 4.
Changing int by long long fixed the issue.  I am not a C guru, so I may be wrong but OCaml's nativeint may not be int of the underlying C compiler. 
In C sizeof(int) may not be 8 on a 64-bit platform. 
If you wish to use the nativeint type in your C bindings the simplest is to include <caml/config.h> and use the intnat type defined there. 
So to rewrite your example:
/* nativeintarray.c */
#include <stdio.h>
#include <assert.h>
#include <caml/config.h>
#include <caml/memory.h>
#include <caml/bigarray.h>
CAMLprim value make_array(value unit) {
  CAMLparam1(unit);
  intnat* a = calloc (1, sizeof(intnat));
  a[0] = -1;
  /* Create a C-style bigarray, yes it is a memory leak */
  CAMLreturn(caml_ba_alloc_dims(CAML_BA_NATIVE_INT | CAML_BA_C_LAYOUT, 1, a, 1));
}
                        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