ocaml-ctypes
ocaml-ctypes copied to clipboard
CIL to Ctypes interface
Just keeping this issue to remind myself that I started working on a simple CIL -> Ctypes transformer that got this far in 10 minutes:
$ opam install cil
$ gcc -E /usr/include/ncurses.h > tmp.h
# utop
# require "cil";;
let f = Frontc.parse "tmp.h" () in
let print_typ typ = Pretty.sprint ~width:50 (Cil.d_type () typ) in
Cil.(iterGlobals f (function |GVarDecl(
{vname; vtype=TFun(rty,Some attr,_,_)},_) ->
Printf.printf "%s (%s) -> %s\n" vname
(String.concat ", " (List.map (fun (_,ty,_) ->
print_typ ty) attr)) (print_typ rty) |_ -> () ));;
which outputs from the C header file:
use_screen (SCREEN *, int (*)(SCREEN * , void * ), void *) -> int
use_window (WINDOW *, int (*)(WINDOW * , void * ), void *) -> int
wresize (WINDOW *, int , int ) -> int
nofilter () -> void
wgetparent (WINDOW const *) -> WINDOW *
is_cleared (WINDOW const *) -> _Bool
is_idcok (WINDOW const *) -> _Bool
is_idlok (WINDOW const *) -> _Bool
is_immedok (WINDOW const *) -> _Bool
A bit more work and that could turn into a Ctypes call, and we could have a camlp4 extension that lets you write "#include <ncurses.h>" and automatically import in type-safe OCaml calls. A ppx equivalent should also be straightforward with an extension_point.
I'd just like to make a note here regarding using CIL for this purpose: I have found that using CIL to parse a pre-processed header file on OSX fails due to the OSX standard library containing functions using block pointers.
I have been trying to auto-generate the Ctypes binding code for enums but ran into the above issue. As far as I know (at least the version of CIL I have installed) can't parse function prototypes which use block pointers.
I could generate a header file which has been preprocessed using:
gcc -E -nostdinc <headerfile>
this then does not include the function prototypes using block pointers but the resulting file will not contain types (e.g. bool or size_t) from the standard library and CIL will again complain that it can't parse the processed file: I can't see an option to get CIL to ignore this and just give me the parse tree.
I have hacked around this by adding typedefs containing bool, size_t, unint64_t to the processed header file by hand, which CIL can then parse, but this is a not a nice way of solving the problem.
It may be that using clang (via clang-ocaml?) is a better option than CIL.
There's a start on a CIL-based bindings generator here.