Ocaml/C 使用 bigarray 的互操作:'undefined symbol: caml_ba_alloc'

Ocaml/C interop using bigarray: 'undefined symbol: caml_ba_alloc'

我正在尝试编译使用 bigarray 的 'Hello World' 级 Ocaml/C 互操作程序。我收到有关 undefined symbol: caml_ba_alloc 的错误(详情如下)。好像应该由bigarray.h.

提供

这是我的文件:

wrap_mylib.c:

#include <caml/bigarray.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>

CAMLprim value caml_fn(value x) {
    float* result = malloc(sizeof(float));
    long dims[] = {1, 1};

    return caml_ba_alloc(CAML_BA_NATIVE_INT, 2, result, dims);
}

mylib.ml:

external ext_caml_fn : int -> (float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array2.t
  = "caml_fn" ;;

Makefile:

wrap_mylib.o: wrap_mylib.c
    gcc -c wrap_mylib.c

another_wrapper.so: wrap_mylib.o
    cc -shared -o another_wrapper.so wrap_mylib.o

mylib.mli: mylib.ml
    ocamlc -i $< > $@

mylib.cmi: mylib.mli
    ocamlc -c $<

mylib.cmo: mylib.ml mylib.cmi
    ocamlc -c $<

mylib_test: mylib.cmo another_wrapper.so
    ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so

clean:
    rm *.cma *.cmo *.cmi *.cmx *.cmxa *.mli *.o *.a *.so

这是我尝试编译时的输出 mylib_test:

$ make mylib_test
ocamlc -i mylib.ml > mylib.mli
ocamlc -c mylib.mli
ocamlc -c mylib.ml
gcc -c wrap_mylib.c
cc -shared -o another_wrapper.so wrap_mylib.o
ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so
File "_none_", line 1:
Error: Error on dynamically loaded library: ./another_wrapper.so: ./another_wrapper.so: undefined symbol: caml_ba_alloc
Makefile:17: recipe for target 'mylib_test' failed
make: *** [mylib_test] Error 2

环境

OS: Ubuntu 18.04.2 LTS(仿生海狸)

$ ocaml --version
The OCaml toplevel, version 4.05.0

谢谢!

bigarray.h这样的文件定义了在编译时有用的东西。但是你的问题是link次的问题。您需要找到包含您要查找的函数的库,并将其包含在 link 步骤中。

如果我使用 ocamlopt(本机代码实现)并使用普通目标文件(OCaml .cmx 和 C .o)而不是共享库,我可以像这样 link 得到东西:

$ ocamlopt -c mylib.ml
$ gcc -I $(ocamlc -where) -c wrap_mylib.c
$ ocamlopt -o mylib_test wrap_mylib.o mylib.cmx

这会生成一个可执行文件 mylib_test 我可以 运行:

$ ./mylib_test
$

当然,当我 运行 可执行文件时什么也没有发生,因为你的文件 mylib.ml 中没有顶级代码。所以这只是测试事情是否会 link 正常。

希望对您有所帮助。

回答我自己的问题。这是我如何让它工作的。通过链接 bigarray.cma:

编译 mylib_test
ocamlc -linkall -o mylib_test mylib.cmo another_wrapper.so bigarray.cma

然后 运行 与:

LD_LIBRARY_PATH=. ./mylib_test

LD_LIBRARY_PATH=. 是它在同一目录中找到共享库 another_wrapper.so 所必需的。

根据 https://caml.inria.fr/pub/docs/manual-ocaml/libbigarray.html bigarray 现在是标准库的一部分,因此只有在使用旧版兼容性库时才需要链接 bigarray.cma。可能是我的标准库版本太旧了。