Как передать конструкцию OCaml (или Bigarray) на C? - PullRequest
0 голосов
/ 04 мая 2020

Я хочу передать буфер сетевого пакета в C. Я уже понял, как это сделать для простых типов OCaml, но я не знаю, как передать буфер из этой библиотеки CStruct.

Используемая мной библиотека использует https://github.com/mirage/ocaml-cstruct который я не знаю почему, но похоже, что он имитирует структуру C, поэтому я думаю, что это должно быть легко передать как буфер в C.

Вот как в моем коде создается буфер:

let buf = Cstruct.create size in

Если мы посмотрим на его код, он вызывает https://github.com/mirage/ocaml-cstruct/blob/master/lib/cstruct.ml#L98

let buffer = Bigarray_compat.(Array1.create char c_layout len) in
  { buffer ; len ; off = 0 }

Для последней версии OCaml Bigarray - это просто стандартная библиотека Bigarray, это просто модуль, который

include Stdlib.Bigarray

Я не мог Вы не найдете ничего о передаче большого массива в C в качестве указателя, который можно прочитать.

1 Ответ

0 голосов
/ 05 мая 2020

интерфейс. cc:

#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/alloc.h>
#include <caml/bigarray.h>

uint8_t *return_big_array()
{
    static const value *make_and_fill_array_closure = NULL;
    if (make_and_fill_array_closure == NULL)
    {
        make_and_fill_array_closure = caml_named_value("make_and_fill_array");
        if (make_and_fill_array_closure == NULL)
        {
            printf("couldn't find OCaml function");
            std::exit(1);
        }
    }
    value bigArrayValue = caml_callback(*make_and_fill_array_closure, Val_unit);
    void *bigArrayPointer = Caml_ba_data_val(bigArrayValue);
    uint8_t *p = (uint8_t *)bigArrayPointer;
    return p;
}

основной. cc

#include <stdio.h>
#include <caml/callback.h>

extern uint8_t* return_big_array();

int main(int argc, char ** argv)
{

  /* Initialize OCaml code */
  caml_startup(argv);
  /* Do some computation */
  uint8_t* p = return_big_array();
  //Should print 5
  printf("first element: %d \n", p[0]);
  return 0;
}

bigarray.ml :

open Format

let make_byte_array len = 
    Bigarray.Array1.create Bigarray.int8_signed Bigarray.c_layout len 

let make_and_fill_array () =  
    let b = make_byte_array 10 in 
    let s = Bigarray.Array1.fill b 5 in
    b

let () = Callback.register "make_and_fill_array" make_and_fill_array

Компиляция:

ocamlopt -output-obj -o s.o bigarray.ml
g++ -o bigarray -I $(ocamlopt -where) \
    main.cc interface.cc s.o $(ocamlopt -where)/libasmrun.a -ldl
...