2016-08-05 70 views
6

Ich möchte int-Arrays von einer C-Bibliothek zu einem OCaml-Programm zurückgeben. Um das zu tun, dachte ich, ich würde sie einfach in eine Bigarray.Array1.t verpacken. Nachfolgend finden Sie eine kleine Kostprobe des C-Stubs:Nativeint Bigararray scheint nicht signiert zu sein

/* 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)); 
} 

Mein Beispielprogramm sieht wie folgt aus:

(* 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} 

Da nativ eine signierte ganze Zahl ist, erwarte ich, dass das Programm zur Ausgabe von -1, sondern es gibt:

% 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 

Wie gesagt, ich naiv nativeint erwartet, dass die int in meinen lokalen C-Compiler passen, aber das ist offensichtlich nicht der Fall. Kann jemand das erklären?

Plattform: Ocaml 4.02.3, gcc 6.1.1, alle 64-Bit-

Antwort

3

Sie sizeof(int) geprüft haben, ist wirklich 8 in Ihrer Umgebung?

In Win64, OCaml 4.03.0 mit x86_64-w64-mingw32-gcc (MinGW64 Compiler von Cygwin), der Code läuft nur haben Sie beschrieben (prints 4294967295, statt -1). Dort gibt sizeof(int)nicht zurück 8 sondern 4.

Ändern int von long long behoben das Problem. Ich bin kein C Guru, also kann ich mich irren, aber OCaml nativeint ist möglicherweise nicht int des zugrundeliegenden C-Compilers.

2

In C sizeof(int) möglicherweise nicht 8 auf einer 64-Bit-Plattform.

Wenn Sie den Typ in Ihren C-Bindungen verwenden möchten, ist der einfachste Weg, <caml/config.h> einzuschließen und den dort definierten Typ intnat zu verwenden.

So Ihr Beispiel neu zu schreiben:

/* 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)); 
}