C FFI - Can I get a function pointer from a value - not using ctypes

ffi

#1

I’m trying to wrap up some C that makes extensive use of function pointers. How can I get a function pointer out of an ocaml value? I looked at how ctypes generated the stubs for something like this, but there was a mysterious funptr(arg) in the resulting C that I couldn’t find the definition of.

What I’m after is:

typedef int (*int_to_int)(int input);

int_to_int foo(value ocaml_fn) {
    // assuming ocaml_fn is of type int -> int
    // some code here to get a function pointer
    return(funptr);
}

Thanks


#2

The way I normally store pointers in OCaml values is in a string. So you would allocate the memory using something like ml_p = caml_alloc_string(sizeof int_to_int) and copy the the pointer into this with memmove(String_val(ml_p), (char *)fp, sizeof int_to_int)

Getting the data back out will just be the reverse: memmove((char *)fp, String_val(ml_p), sizeof int_to_int).

However, it really depends on how the function pointer was stored in the OCaml value.


#3

@blez - I think you’ve misunderstood the question, which is how to obtain a C function pointer to an OCaml function, not how to store a C function pointer in an OCaml value.


#4

@blez - as an aside, it would be better to be using custom blocks, as GodDamien intended, rather than (ab)using strings!


#5

@dra27 - I’ve seen both used for simple pointers (ones that don’t need to be free’d before the GC) but agree custom blocks are generally better.

Sorry for the confusion on the callbacks.


#6

@sagra: I had a look at this as I haven’t done this before (full disclosure!) but I think it should be doable if you combine the C library FFCALL (or GNU’s version) with the OCaml callback API. You would generate a new function with the OCaml closure as a parameter and pass this as the callback function. This will also need custom blocks as you will need to free memory when a callback goes out of scope

Depending on your library API the functions may also have a callback parameter (usually void *) that get’s passed to the callback blindly, in which case you can put the closure value ih this.

I hope this helps.