Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static function pointers for stubs and inverted stubs #711

Open
sim642 opened this issue Jun 19, 2022 · 1 comment
Open

Static function pointers for stubs and inverted stubs #711

sim642 opened this issue Jun 19, 2022 · 1 comment

Comments

@sim642
Copy link

sim642 commented Jun 19, 2022

Use case

Currently it is possible to use foreign to declare C functions that take function arguments via static_funptr. In various places (including issues of this repository) it is shown how to coerce such function pointers from Foreign.funptrs, which add the libffi dependency. And as far as I can find, there's no other way to construct static_funptrs.

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 even internal). 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 as static_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 use foreign_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:

  1. Add another function like foreign_funptr: string -> 'a fn -> 'a static_funptr to FOREIGN, which is very similar to foreign_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 from unit to a corresponding static_funptr for the pointer to the inverse stubbed C function.

  2. 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 for internal 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).

@yallop
Copy link
Owner

yallop commented Jun 20, 2022

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants