Можно ли передать функцию C в качестве обратного вызова в OCaml? - PullRequest
0 голосов
/ 01 мая 2020

Я изучаю, как интегрировать стек TCP / IP OCaml в мой проект C ++. Я уже знаю, как вызвать C из OCaml и вызвать OCaml из C благодаря этому ответу: OCaml как C библиотека, пример Hello World

Управляется OCaml С ++, а не наоборот. Итак, для стека TCP / IP я должен иметь возможность отправлять и получать пакеты. Я легко могу отправить данные в стек TCP / IP через C ++, но как их получить? Мне нужно передать функцию C (обратный вызов) в качестве параметра в OCaml, чтобы он доставлял данные при поступлении. Возможно ли это?

1 Ответ

3 голосов
/ 08 мая 2020

Для этого вам нужны две 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. Их можно безопасно удалить, поскольку функция является просто оберткой для фактической функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...