Cstubs_structs and callbacks

I’m trying to use Cstubs to talk to a C API that features structs containing both enums and callbacks. As far as I understand, the way to go about this is to define all the types in a functor parameterized by a Ctypes.TYPE, however this does not seem to allow for callbacks. As a minimal example, the code below compiles fine but raises a IncompleteType exception at runtime, because of the use of the (seemingly complete) struct point.

module C (T : Ctypes.TYPE) = struct
  open Ctypes
  open T

  type point
  let point : point structure typ = structure "point"
  let x = field point "x" int64_t
  let y = field point "y" int64_t
  let () = seal point

  type callback
  let callback : callback structure typ = structure "callback"
  let get_point = field callback "get_point" (static_funptr (void @-> returning point))
  let () = seal callback
end


let () =
  let f = Format.formatter_of_out_channel (open_out "generate_bindings.c") in
  Cstubs_structs.write_c f (module C)

I understand I could probably generate bindings in multiple stages, but I would much rather avoid that, if at all possible.

@malva What I see here is

let get_point = field callback "get_point" (static_funptr (void @-> returning point))

This line is problematic because:

  • you use a structure type (like point ) as the return type in a static_funptr, ctypes need to know the size and the layout of your struct
  • However, for callback function types (static_funptr) , Cstubs_structs cannot always guarantee that the necessary size and alignment information for the structure is available at the point of processing the function pointer’s type, leading to the structure being considered an incomplete type in that context.

First, you need check the C API, is it really return struct by value (which is should not the case!).

Most common C API is either return a pointer or take a pointer to be modified. If your C API really return a struct by value, you need to wrap it and make it take a pointer instead.

After that, change the definition to:

let get_point = field callback "get_point" (static_funptr (void @-> returning (ptr point)))