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