Для этого вам нужны две C функции. Первый (wrap_fun
ниже) вызывается из кода C. Он принимает обратный вызов C и возвращает значение OCaml, которое затем можно передать в свой код OCaml. Второй (call_wrapped
ниже) вызывается из кода OCaml. Он принимает значение OCaml, созданное первой функцией, и вызывает сохраненный в ней обратный вызов.
Вы ничего не указали в сигнатуре обратного вызова, поэтому приведенный ниже код относится к 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);
}
На стороне OCaml это выглядит следующим образом:
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"
Макросы CAMLparam2
и CAMLreturn
в call_wrapped
предназначены только для целей didacti c. Их можно безопасно удалить, поскольку функция является просто оберткой для фактической функции.