Questions about ctypes funptr and const pointer

Hello everyone,

I’m currently writing an OCaml binding to LXC (Linux Containers), and have some questions w.r.t. usage of ctypes.

1. Using function pointer as function?

My understanding after going through the ctypes document is one can convert an OCaml function to a function pointer to C side, carry function pointer around etc, but cannot use a C function pointer in OCaml’s side directly as if it’s a normal OCaml function.

Is this correct?

EDIT:
Context is LXC stores function pointers in the main struct (lxc_container), and one would invoke the function via lines like c->do_stuff(c, arg1, arg2, ...) to access the functionality.
Right now I’m relying on glue code generated using cinaps to access and invoke function pointer on C’s side, which seems to work fine. But I’m curious if there’s a better way.

2. Equivalent of const * in ctypes?

It seems that I cannot specify a const pointer via ctypes, which would make sense, but I want to double check I’m not being silly in any case.

Thanks very much for your time!
Darren

1 Like

My understanding after going through the ctypes document is one can convert an OCaml function to a function pointer to C side, carry function pointer around etc, but cannot use a C function pointer in OCaml’s side directly as if it’s a normal OCaml function.

Is this correct?

In fact, the conversion works both ways; you can use a C function pointer as an OCaml function on the OCaml side. Here’s a little working example:

/* funlib.c */
struct adder { int (*add) (int, int); };
int add(int x, int y) { return x + y; }
extern struct adder make_adder(void) { return (struct adder){ .add = add }; }
$ gcc -shared -o libfun.so -std=c99 -fPIC -pedantic -W -Wall funlib.c 
(* fun.ml *)
#use "topfind";;
#require "ctypes.foreign";;

open Ctypes
open Foreign

let adder = structure "adder"
let add = field adder "add" (funptr (int @-> int @-> returning int))
let () = seal adder

let libfun = Dl.(dlopen ~filename:"./libfun.so" ~flags:[RTLD_NOW])
let make_adder = foreign "make_adder" (void @-> returning adder)
               ~from:libfun

let () =
  let s = make_adder () in
  Printf.printf "add(3,4) = %d\n" (getf s add 3 4)
$ ocaml fun.ml 
add(3,4) = 7

It seems that I cannot specify a const pointer via ctypes, which would make sense, but I want to double check I’m not being silly in any case.

That’s correct: there’s currently no support for const. (Adding #define const before you #include a file in generated C code will probably give you something that works, even if it’s not strictly legitimate.)

2 Likes

Thanks for the detailed reply!

One silly question just to check my sanity - the above would work the same for stub generation case I presume?

EDIT: specifically the static_funptr case.

EDIT2: Ended up using coerce, e.g.

let is_defined' (c : Types.lxc_container structure ptr) =
  let c_field = getf (!@c) Type_stubs.is_defined in
  let f = coerce (field_type Type_stubs.is_defined)
      (Foreign.funptr (ptr Types.lxc_container @-> returning bool)) c_field
  in
  f c