【问题标题】:How to pass an OCaml cstruct (or Bigarray) to C?如何将 OCaml cstruct(或 Bigarray)传递给 C?
【发布时间】:2020-08-18 10:06:14
【问题描述】:

我想将一个网络数据包的缓冲区传递给 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

我找不到任何关于将 bigarray 作为可以读取的指针传递给 C 的信息。

【问题讨论】:

  • 这和函数式编程有什么关系?

标签: functional-programming ocaml


【解决方案1】:

interface.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;
}

ma​​in.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

【讨论】:

    猜你喜欢
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多