(This is something I did in December but have only just gotten round to posting about)
The OCaml Unix module provides many of the system calls needed for day-to-day work, but occasionally there is one that is only available in C. In a recent project, I needed to find a PID from a semaphore ID when parsing the output of:
$ ipcs -s ------ Semaphore Arrays -------- key semid owner perms nsems 0xd69fd280 1638401 oracle 660 504 <snip>
To interface a C library with an OCaml program there are three elements:
- The interface file which maps between C and OCaml function names
- The stub file which wraps C functions in OCaml datatypes
- The actual OCaml program itself that does the work
Here I will show a stripped down example of doing this for semctl(). First the interface file semctl.mli:
external semctl: int -> int = "caml_semctl"
This is very simple, as in this example we are only using the one function. It takes an int as an argument and returns another int. Next the stub file semctl_stub.c:
#include <sys/sem.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
#include <caml/custom.h>
value caml_semctl(value semid) {
CAMLparam1(semid);
CAMLreturn(Val_int(semctl(Int_val(semid), 0, GETPID)));
}
Notice the name from the interface file is prefixed caml_ to avoid clashing with the actual C function, because I still want to call it by its C name in the main OCaml program. The parameter is cast from OCaml→C type and the return value cast back again (all on the stack). Finally the main OCaml program semctl_getpid.ml:
open Semctl
open Unix
open Printf
let () =
match (Array.length Sys.argv) with
| 2 -> print_endline (sprintf "%d\n" (semctl (int_of_string Sys.argv.(1))))
| _ -> prerr_endline (sprintf "Usage: %s <semid> " Sys.argv.(0))
To compile and link these three components:
$ ocamlc -c semctl.mli $ ocamlc -c semctl_stub.c $ ocamlc -custom -o semctl_getpid unix.cma semctl_getpid.ml semctl_stub.o
Then running it:
$ ./semctl_getpid 1638401 9022 $ ps -e|grep 9022 9022 ? 00:00:03 sp_cop
Exactly as expected, one of the components of Shareplex. Anyway, knowing this technique moves me a little closer to my eventual goal of maintaining my own native Oracle bindings.

You should add this to the ExtUnix library: http://extunix.forge.ocamlcore.org/
Ah interesting, I did not know about this