问题
I'm studying on how to integrate an OCaml TCP/IP stack into my C++ project. I already know how to call C from OCaml and call OCaml from C thanks to this answer: OCaml as C library, hello world example
The OCaml will be controlled by C++, not the other way around. So, for a TCP/IP stack, I must be able to send and receive packets. I can easily send data to the TCP/IP stack through C++, but how to receive it? I need to pass a C function (a callback) as a parameter to OCaml so it delivers the data when it arrives. Is it possible?
回答1:
You need two C functions for that. The first one (wrap_fun
below) is called from C code. It takes a C callback and returns an OCaml value that you can then pass to your OCaml code. The second one (call_wrapped
below) is called from the OCaml code. It takes an OCaml value created by the first function and calls the callback stored into it.
You did not specify anything about the signature of your callback, so the code below goes for value(value)
.
#include <caml/alloc.h>
#include <caml/memory.h>
#include <caml/mlvalues.h>
typedef value (*cb)(value);
value wrap_fun(cb f) {
value v = caml_alloc_small(1, Abstract_tag);
Field(v, 0) = (value)f;
return v;
}
value call_wrapped(value f, value x) {
CAMLparam2(f, x);
cb g = (cb)Field(f, 0);
value z = g(x);
CAMLreturn(z);
}
On the OCaml side, it looks as follows:
external call_wrapped : ('a, 'b) wrapped_fun -> 'a -> 'b = "call_wrapped"
let foo f x =
let y = x + 1 in
let z = call_wrapped f y in
z ^ "a"
The CAMLparam2
and CAMLreturn
macros in call_wrapped
are just there for didactic purpose. They can safely be removed, since the function is just a wrapper to the actual function.
来源:https://stackoverflow.com/questions/61537623/is-it-posible-to-pass-a-c-function-as-callback-to-ocaml