Foreign Function Interface
Structs, pointers, callbacks, and stub generation (ctypes.stubs) for performance and portability.
39.1 external declarations with C stubs
(* math.ml *)
external c_add : int -> int -> int = "caml_c_add"/* stubs.c */
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
CAMLprim value caml_c_add(value a, value b) {
CAMLparam2(a, b);
CAMLreturn(Val_int(Int_val(a) + Int_val(b)));
}(library (name math) (foreign_stubs (language c) (names stubs)))39.2 Key rules for C stubs
Use CAMLparam, CAMLlocal, CAMLreturn to register roots with the GC.
Conversions: Int_val/Val_int, Double_val/caml_copy_double, String_val/caml_copy_string, Bool_val/Val_bool, Field(v, i), Store_field.
Allocation: caml_alloc, caml_alloc_tuple, custom blocks (caml_alloc_custom) for C resources with finalizers.
Raising: caml_failwith, caml_invalid_argument, caml_raise_not_found.
Release the runtime lock around long blocking calls: caml_release_runtime_system() / caml_acquire_runtime_system() (formerly caml_enter/leave_blocking_section).
[@@noalloc], [@unboxed], [@untagged] for zero-overhead calls on floats/ints.
More than 5 args → need separate bytecode and native stubs.
39.3 ctypes — FFI without writing C
Structs, pointers, callbacks, and stub generation (ctypes.stubs) for performance and portability.
open Ctypes
open Foreign
let puts = foreign "puts" (string @-> returning int)
let strlen = foreign "strlen" (string @-> returning size_t)
let () = ignore (puts "Hello from C!")39.4 Calling OCaml from C
caml_named_value, caml_callback, Callback.register "name" f; build with -output-obj to embed OCaml in a C application.
39.5 Other interop
Rust: ocaml-rs, ocaml-interop.
Python: pyml.
JavaScript: js_of_ocaml / Melange (§45).