# Calling Ocaml C FFI using Ctypes pointers

**URL:** <https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336>\
**Category:** Ecosystem\
**Tags:** ctypes, ffi\
**Created:** [September 30, 2025, 9:39am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336 "2025-09-30T09:39:46Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [September 30, 2025, 9:39am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/1 "2025-09-30T09:39:46Z")

</div>

My question:

Is there a well-understood way to mix `Ctypes.Foreign` data structures with Ocaml C Stubs FFI? I am running into some corruption issues because I think I am doing this translation incorrectly.

Background:

I wrote `kqueue` bindings using `Ctypes.Foreign`, however due to some static linking reasons, I have decided to implement the bindings via classic Ocaml C FFI. I would like to continue to use Ctypes to generate bindings for the various structs and constants I need access to, for example the event list structure. Is it well-defined how to use a Ctypes `ptr` when calling Ocaml C FFI.

Here is the definition of my bindings:

> <https://github.com/terrateamio/terrateam/blob/208-add-kv-store/code/src/kqueue/kqueue.ml#L63-L94>

I’m managing my event list via `allocate_n`

> <https://github.com/terrateamio/terrateam/blob/208-add-kv-store/code/src/kqueue/kqueue.ml#L9-L17>

And I am trying to call it using with: `(Ctypes.raw_address_of_ptr @@ Ctypes.to_voidp changelist.Eventlist.kevents)`

And finally, I try to convert it back to the C representations with:

> <https://github.com/terrateamio/terrateam/blob/208-add-kv-store/code/src/kqueue/kqueue_fun_stubs.c#L13-L21>

However, I seem to be getting some corruption at some point in running my program (note, this corruption has not been happening in running with `Ctypes.Foriegn` for several years, so it IS something to do with what I’m doing here).

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [September 30, 2025, 10:20am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/2 "2025-09-30T10:20:53Z")

</div>

I think I’m possibly seeing something around Garbage collection compaction? Although, I’m just guessing. The bad data looks like the following at the syscall level:

15585 759036 terrat\_ee.native 287.548822907 CALL kevent(0x4,0x338530457dc0,0x1,0x338531030240,0x400,0x33852d23d5f0)  
15585 759036 terrat\_ee.native 287.548940822 STRU struct kevent = { { ident=0x5a5a5a5a5a5a5a5a, filter=\<invalid=0x5a5a\>, flags=0x5a5a\<EV\_DELETE|EV\_DISABLE|EV\_KEEPUDATA|EV\_ONESHOT|EV\_RECEIPT|EV\_ERROR\>,  
fflags=0x5a5a5a5a, data=0x5a5a5a5a5a5a5a5a, udata=0x5a5a5a5a5a5a5a5a } }  
15585 759036 terrat\_ee.native 287.548961975 STRU struct kevent = { { ident=0x5a5a5a5a5a5a5a5a, filter=\<invalid=0x5a5a\>, flags=0x4000\<EV\_ERROR\>, fflags=0x5a5a5a5a, data=0x16, udata=0x5a5a5a5a5a5a5a5a } }

---

<div class="post-metadata">

**Author:** ![lindig](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lindig/32/532_2.png) [@lindig](https://discuss.ocaml.org/u/lindig)\
**Post date:** [September 30, 2025, 10:21am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/3 "2025-09-30T10:21:20Z")

</div>

```auto
void* ctypes_ptr(value v) {

```

Is this not missing `CAMLparam1(v)`? And using `CAMLreturn`?

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [September 30, 2025, 10:23am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/4 "2025-09-30T10:23:04Z")

</div>

This is a helper function, not called directly from Ocaml, but from the C code Ocaml is calling. I believe I only have to do the OCaml FFI macros in the function that is being called directly.

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [September 30, 2025, 11:15am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/5 "2025-09-30T11:15:15Z")

</div>

Knock on wood, I think I found the solution. After digging around ctypes code it looks like it wraps points in a Fat pointer, which is really just a record with your Ocaml value in it + the pointer value. I’m running our test suite now and it seems to be working.

---

<div class="post-metadata">

**Author:** ![Chimrod](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chimrod/32/6042_2.png) [@Chimrod](https://discuss.ocaml.org/u/Chimrod)\
**Post date:** [September 30, 2025, 11:55am UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/6 "2025-09-30T11:55:07Z")

</div>

As long it is not documented/specified, it is like using `magic` in the code. There is no guarantee that the behavior will stay valid over time.

---

<div class="post-metadata">

**Author:** ![orbitz](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/orbitz/32/110_2.png) [@orbitz](https://discuss.ocaml.org/u/orbitz)\
**Post date:** [September 30, 2025, 12:00pm UTC](https://discuss.ocaml.org/t/calling-ocaml-c-ffi-using-ctypes-pointers/17336/7 "2025-09-30T12:00:55Z")

</div>

Once I validated the Fat ptr trick worked, I switched over to my own “fat pointer” implementation so I can be guaranteed the structure won’t change.
