Advanced C binding using ocaml-ctypes and dune

Hi there!

I worked on a socket.h binding last summer and had a great experience integrating ocaml-ctypes with dune, I thought that might be of interest to other developers so I wrote about it: https://medium.com/@romain.beauxis/advanced-c-binding-using-ocaml-ctypes-and-dune-cc3f4cbab302

Romain

7 Likes

This is a good article. I encourage anyone who writes C bindings with ctypes to study it carefully.

A little bit of advice to shorten your dune files:

 (deps    (:gen ./gen_constants_c.exe))

This line isn’t necessary. Dune is smart enough to know that running a binary in a rule incurs a dependency on it.

dune has a truly amazing support for cross-compiling, which we do not cover here, but, unfortunately, its primitives for building and executing binaries do not yet cover this use case.

Indeed, we don’t have any primitives for running binaries on the target platform. Perhaps we should add some. However, we do in fact have some features in dune to solve this concrete cross compilation problem. As far as I understand, the goal is to obtain some compile time values such as #define constants and field offsets for the target platform. This does not in fact require to run anything on the cross compilation target. In configurator, we have a primitive C_define.import to extract this information. The end result is that these configurator scripts are completely compatible with cross compilation.

Perhaps this could be generalized to work with ctypes generators as well?

Funny bit of trivia: The hack in configurator required to do this is in fact something I extracted from ctypes itself. The original author is whitequark, who in turn wrote it to make ctypes itself amendable to cross compilation.

2 Likes

If anybody wants to know more about this bit, I wrote an article about this last year:

4 Likes

Thanks for the feedback y’all!

@rgrinberg A quick glance at the code for C_define seems to indicate that it can only handle static #define of type string, int or bool. Can it also handle cases such as:

#define SOCKLEN sizeof(socklen_t)

?

Romain

Yeah, this case should work as well. I think we even some tests for it in configurator.

Oh, sweet. I’ll give it a try!