ocamllabs/ocaml-ctypes — pull request #150 by yallop (2014-05-16 14:06:58+00:00)
Title: Support for exposing OCaml code as C libraries

Ctypes currently supports importing C functions for use in OCaml. This pull request adds support for making OCaml functions available to C programs.

The interface is similar to the interface for regular stub generation (#129), and again there are three steps:

### Step 1: write the bindings

First, you describe the C types of your OCaml functions in a functor parameterised by the [INTERNAL signature][internal-signature]. For example, to expose the standard library functions [succ][succ] and [Str.index][str-index] to C you start with a module like this:

```ocaml
module Bindings (I : INTERNAL) =
struct
let () = I.internal "succ" Ctypes.(int @-> returning int)
succ
let () = I.internal "str_index" Ctypes.(string @-> char @-> returning int)
String.index
end
```

### Step 2: generate stubs

Stubs come in three parts: a C source file, a C header file, and an OCaml module that links the stubs with the OCaml functions they refer to.

You can generate the three components by passing the `Bindings` functor to [write_c][write_c], [write_c_header][write_c_header] and [write_ml][write_ml]:

```ocaml
Cstubs_inverted.write_c fmt ~prefix:"libfoo_" (module Bindings)
Cstubs_inverted.write_c_header fmt ~prefix:"libfoo_" (module Bindings)
Cstubs_inverted.write_ml fmt ~prefix:"libfoo_" (module Bindings)
```

### Step 3: link the stubs

Finally, you can compile the generated code and link it together with your OCaml library and the OCaml runtime to produce a shared object.

```ocaml
include Bindings(Generated_bindings)
```

The result is a C library that you can use from anywhere that can talk to C. For example, you can call your OCaml code from Python using [Python's ctypes][python-ctypes]:

```python
>>> libfoo = CDLL('libfoo.so')
>>> print libfoo.succ(10)
11
```

(Not shown: you also need to call [caml_startup][caml-startup] to initialize the caml runtime. Full example to follow.)

Warning: module and function names may change before the next release.

Note: Building a shared library requires an OCaml runtime compiled to independent code, such as the OPAM switch [4.01.0+PIC][PIC-runtime].

[succ]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html#VALsucc
[str-index]: http://caml.inria.fr/pub/docs/manual-ocaml/libref/String.html#VALindex
[write_c]: https://github.com/yallop/ocaml-ctypes/blob/0bc36bd6/src/cstubs/cstubs_inverted.mli#L17-L24
[write_c_header]: https://github.com/yallop/ocaml-ctypes/blob/0bc36bd6/src/cstubs/cstubs_inverted.mli#L26-L31
[write_ml]: https://github.com/yallop/ocaml-ctypes/blob/0bc36bd6/src/cstubs/cstubs_inverted.mli#L33-39
[internal-signature]: https://github.com/yallop/ocaml-ctypes/blob/0bc36bd6/src/cstubs/cstubs_inverted.mli#L10-L13
[PIC-runtime]: https://github.com/ocaml/opam-repository/tree/master/compilers/4.01.0/4.01.0%2BPIC
[python-ctypes]: https://docs.python.org/2/library/ctypes.html
[caml-startup]: https://github.com/ocaml/ocaml/blob/6d25df3c9b/byterun/callback.h#L47