Open sim642 opened 2 years ago
At the moment I think the easiest way to do this is to add a line of C to create a function pointer to the function you want to bind. For example, if you want to bind a function
int compare (void *, void *);
then you could add an additional line as follows
static int (*compare_pointer) (void *, void *) = &compare;
and then bind compare_pointer
using static_funptr
and foreign_value
like this:
let compare = foreign_value "compare_pointer"
(static_funptr (ptr void @-> ptr void @-> returning int))
When attempting to use
foreign_value
with a function name and type, there's an undesired extra level of pointer
Returning a pointer from foreign_value
is a more general interface than returning the value directly, since it supports both reading and writing (as well as repeated reading of a changing value).
Use case
Currently it is possible to use
foreign
to declare C functions that take function arguments viastatic_funptr
. In various places (including issues of this repository) it is shown how tocoerce
such function pointers fromForeign.funptr
s, which add the libffi dependency. And as far as I can find, there's no other way to constructstatic_funptr
s.However, it might be that in the OCaml code, one might want to pass a (static) function pointer of another C function (be it another
foreign
or eveninternal
). Since such function's pointer can be statically taken, there should be no need to involve ctypes.foreign. There should just be a way to get an'a static_funptr
from a function name and'a fn
. That would allow passing one C function as an argument to another C function directly.Furthermore, without discrimination it should equally well be possible to get the function pointer of an inverted stub
internal
asstatic_funptr
and pass it to other C functions. Although the final implementation is in OCaml, it would avoid the need for ctypes.foreign since there exists a static C function for it.Current state
As far as I can find, there is currently no way to do so. The closest I could find is
foreign_value
, which doesn't seem to be described anywhere. When attempting to useforeign_value
with a function name and type, there's an undesired extra level of pointer. Namely, that would give'a static_funptr ptr
, which is a pointer to a pointer to a function. Moreover, the generated C stub emits compiler warnings for incompatible pointer types where it assigns a function pointer to a double pointer.Possible solutions
I'm not intimately familiar with the internals of ctypes, but from I understand I can think of two solutions:
Add another function like
foreign_funptr: string -> 'a fn -> 'a static_funptr
toFOREIGN
, which is very similar toforeign_value
, but handles function pointers correctly and doesn't do use invalid double pointers and provides a function-pointer-specific signature. For inverted stubs, their return type could be changed fromunit
to a correspondingstatic_funptr
for the pointer to the inverse stubbed C function.In the spirit of modularity of ctypes, it might be possible to provide alternative families of forward and inverted stub generators that for
foreign
give the function pointer (instead of the callable OCaml function) and forinternal
give the function pointer (instead of unit). This would leave all existing interfaces untouched, preserving compatibility, but would require additional C and OCaml stub generators for both directions.In turn, it would allow joint inverted stubbing and their function pointer taking such that an OCaml function can be passed as
static_funptr
to some C stubs with no ctypes.foreign involvement. This could cover many uses of inverted stubbing where the OCaml functions are fixed, rather than being arbitrary closures (for which you'd still need ctypes.foreign for).