# Advanced C binding using ocaml-ctypes and dune

**URL:** <https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805>\
**Category:** Learning\
**Tags:** ctypes, bindings, build, dune\
**Created:** [December 2, 2019, 8:31am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805 "2019-12-02T08:31:41Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 2, 2019, 8:31am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/1 "2019-12-02T08:31:41Z")

</div>

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](https://medium.com/@romain.beauxis/advanced-c-binding-using-ocaml-ctypes-and-dune-cc3f4cbab302)

Romain

---

<div class="post-metadata">

**Author:** ![rgrinberg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rgrinberg/32/40_2.png) [@rgrinberg](https://discuss.ocaml.org/u/rgrinberg)\
**Post date:** [December 2, 2019, 3:47pm UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/2 "2019-12-02T15:47:39Z")

</div>

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:

```auto
 (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](https://dune.readthedocs.io/en/latest/cross-compilation.html), 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](https://github.com/whitequark), who in turn wrote it to make ctypes itself amendable to cross compilation.

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [December 2, 2019, 4:38pm UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/3 "2019-12-02T16:38:46Z")

</div>

> [@rgrinberg](#):
>
> 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.

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

> **[How configurator reads C constants](https://dune.build/blog/configurator-constants/)**
>
> Dune comes with a library to query OS-specific information, called configurator. It is able to evaluate C expressions and turn them into OCaml value. Surprisingly,...

---

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 3, 2019, 9:39am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/4 "2019-12-03T09:39:03Z")

</div>

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:

```auto
#define SOCKLEN sizeof(socklen_t)

```

?

Romain

---

<div class="post-metadata">

**Author:** ![rgrinberg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rgrinberg/32/40_2.png) [@rgrinberg](https://discuss.ocaml.org/u/rgrinberg)\
**Post date:** [December 3, 2019, 10:31am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/5 "2019-12-03T10:31:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 3, 2019, 10:33am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/6 "2019-12-03T10:33:25Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 27, 2019, 1:29am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/7 "2019-12-27T01:29:18Z")

</div>

Hi! Just getting back to this.

Unfortunately, I don’t think that configurator will be enough. The build system also uses ctypes support for structures, which needs to compile and run using the cross-compiler in order to calculate the right sizes and offsets for the structures and their fields. As a user of the module, I cannot tap into the internals for this process via configurator, my only use is via compiler and executables…

---

<div class="post-metadata">

**Author:** ![XVilka](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/xvilka/32/5334_2.png) [@XVilka](https://discuss.ocaml.org/u/XVilka)\
**Post date:** [December 27, 2019, 4:52am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/8 "2019-12-27T04:52:15Z")

</div>

Ideally, bindings could be generated completely automatically, by parsing C headers with clang and generating appropriate interfaces. Languages that have support for this:

- Python with [ctypeslib2](https://github.com/trolldbois/ctypeslib)
- Rust with [rust-bindgen](https://github.com/rust-lang-nursery/rust-bindgen)
- Go with [c-for-go](https://github.com/xlab/c-for-go)
- Haskell with [c2hs](https://github.com/haskell/c2hs)
- Ada with [GNAT bindings generator](https://gcc.gnu.org/onlinedocs/gnat_ugn/Generating-Ada-Bindings-for-C-and-C_002b_002b-headers.html#Generating-Ada-Bindings-for-C-and-C_002b_002b-headers)

See, for example, how I generate bindings automatically for [radare2](https://github.com/radareorg/radare2) C headers using those in [genbind.py](https://github.com/radareorg/radare2-bindings/blob/master/genbind.py) script. It is very simple and straightforward. I wish something like that existed for OCaml.

---

<div class="post-metadata">

**Author:** ![sid](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sid/32/1476_2.png) [@sid](https://discuss.ocaml.org/u/sid)\
**Post date:** [December 27, 2019, 5:15am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/9 "2019-12-27T05:15:49Z")

</div>

Yes, this is a good point. I was also wondering if there was a tool that did the same in OCaml.

---

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 27, 2019, 5:54am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/10 "2019-12-27T05:54:06Z")

</div>

Having dealt with multiple intricate arch-specific situations, I do not believe that a fully automated solution would work for all cases. It would be a great tool for some easy bindings but as soon as you get into some nitty gritty ones, I would be curious to see how that would be possible.

Couple of examples:

- clock\_t and time\_t in POSIX are arithmetic types, they can be either float or int. How would you generate an automated OCaml API that offers a unified type on all platforms simply based on the C headers? Likewise, although perhaps easier, with int types of indeterminate size such as size\_t and etc.
- flac API is based on callbacks. How do you define the relationship between the callbacks and the garbage collector?

---

<div class="post-metadata">

**Author:** ![sid](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sid/32/1476_2.png) [@sid](https://discuss.ocaml.org/u/sid)\
**Post date:** [December 27, 2019, 6:46am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/11 "2019-12-27T06:46:42Z")

</div>

The best scenario is that automated binding tools can do 90% of the boring binding work. The rest of the intricate work can be done manually. I’m sure that a lot of tools in the other languages also allow some customisations.

---

<div class="post-metadata">

**Author:** ![rgrinberg](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rgrinberg/32/40_2.png) [@rgrinberg](https://discuss.ocaml.org/u/rgrinberg)\
**Post date:** [December 28, 2019, 1:10pm UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/12 "2019-12-28T13:10:20Z")

</div>

This is something that we should be able to fix however. There’s no reason ctypes needs to run any code to calculate sizes and offsets. Unfortunately, our backlog for ctypes + dune is quite large:

- We want to port ctypes to dune
- We want to write a dune extension to simplify the dune boilerplate required

Once we have the above, we could indeed look into fixing cross compilation in ctypes.

---

<div class="post-metadata">

**Author:** ![toots](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/toots/32/3323_2.png) [@toots](https://discuss.ocaml.org/u/toots)\
**Post date:** [December 28, 2019, 3:45pm UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/13 "2019-12-28T15:45:35Z")

</div>

That all sounds great. Cross-compilation is not too important for me as long as we have a workaround like I described.

On a similar topic, after taking to Jeremy Yallop in [ocaml-ctypes#620](https://github.com/ocamllabs/ocaml-ctypes/pull/620) I started what I hope could be a nice common repository of posix bindings, build on `dune` and `ctypes` with shared APIs, patterns and building blocks: [savonet/ocaml-posix](https://github.com/savonet/ocaml-posix)

The idea would be to propose to join all existing posix-related bindings under the same umbrella with both ctypes primitives for low-level bindings and high-level APIs for end-user consumption.

Some bindings would not be moved there, in particular those with a greater scope or additional complexity like [unix-errno](https://github.com/dsheets/ocaml-unix-errno) but for bindings that stick mostly to the posix specs, I think this would be a great step forward to cleanup the existing set of modules.

---

<div class="post-metadata">

**Author:** ![XVilka](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/xvilka/32/5334_2.png) [@XVilka](https://discuss.ocaml.org/u/XVilka)\
**Post date:** [March 24, 2020, 12:39pm UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/14 "2020-03-24T12:39:22Z")

</div>

There is an interesting project inspired by [haskell-gi](https://github.com/haskell-gi/haskell-gi) to automate OCaml bindings generation for GTK+ - [ocaml-gi-gtk](https://github.com/illbexyz/ocaml-gi-gtk).

See more context [here](https://github.com/garrigue/lablgtk/issues/106). The only downside (for OCaml developers) is that it’s written in Haskell.

---

<div class="post-metadata">

**Author:** ![Mhouh](https://avatars.discourse-cdn.com/v4/letter/m/838e76/32.png) [@Mhouh](https://discuss.ocaml.org/u/Mhouh)\
**Post date:** [April 21, 2022, 8:53am UTC](https://discuss.ocaml.org/t/advanced-c-binding-using-ocaml-ctypes-and-dune/4805/15 "2022-04-21T08:53:25Z")

</div>

Now, dune has a ctypes stanza.  
But only does a type and function generation pass, so it does not seem possible to use constants to define types using this stanza, like it is done here…  
Or maybe I am missing something?
