Gregory Nisbet Gregory Nisbet - 1 month ago 19
C Question

OCaml return unboxed float from C function with bytecode compiler

I have a very simple function that calls

in order to get the epoch time and returns it as an unboxed OCaml float.

The platform here is OS X 10.12.6 and I've tested using OCaml versions 4.03.0 and 4.04.0 .

Here is

#include <time.h>
#include <caml/memory.h>

#define IGNORE_UNUSED(x) ( (void)(x) )

CAMLprim double
ocaml_unixtime(value unit)
return (double) time(NULL);

The OCaml code,
looks like this ... it returns an unboxed float and indicates to the compiler that it doesn't perform any OCaml-side allocations.

This function takes less than 5 arguments, so it seems like implementing it once and using that for both the byte code compiler and native compiler should be fine (

external unixtime : unit -> (float [@unboxed]) =
"ocaml_unixtime" "ocaml_unixtime" [@@noalloc];;

let () = Printf.printf "%f\n" (unixtime ())

This example works fine with the native compiler (although I'm a little concerned that the cast to
is not exactly the right thing to do but It Works On My Machine).

% ocamlopt libunixtime.c
% ./a.out

However, when compiling with the bytecode compiler and attempting to run, I get a segfault immediately.

% ocamlc -custom libunixtime.c
% ./a.out
Segmentation fault
Exit 139

Does the bytecode compiler not support unboxed floats? How do I figure out why the behavior differs between the bytecode and native compilers?

Answer Source

First, your code seems to be missing a CAMLparam call for the unit value. This is necessary so that the GC knows about it, see section 19.1.

But there's another more important bug: the bytecode version cannot use unboxed functions (section 19.10), so you'll have to provide an alternative implementation for the bytecode compiler that returns a boxed value using caml_copy_double and CAMLreturn.