【发布时间】:2018-02-15 06:45:50
【问题描述】:
我正在尝试从 OCaml 库中构建一个共享对象,我可以使用 ctypes 中的 cdll 接口在 Python 下运行该共享对象。
有没有办法让 OCaml 工具链中的某些东西生成一个共享对象,并链接其依赖项?
我开始怀疑 OCaml 根本不支持我正在尝试做的事情。我想调用一个 OCaml 函数,然后让它产生某种结果并将控制权返回到调用它的位置。
这是我的 OCaml 库
(* foo.ml *)
let add x y = x + y
而我用来在 OS X 上编译它的命令。(使用.so 而不是.dylib 稍微违反了平台的命名约定,但ocamlopt 将只接受.o 或@ 的扩展名987654329@.)
$ ocamlopt -output-obj -fPIC -o foo.so foo.ml
成功并产生foo.so。
这是我第一次尝试将共享对象加载到 python 程序(python 3.6)中。
# foo.py
import ctypes
lib = ctypes.cdll.LoadLibrary('./foo.so')
print("Loaded")
运行时出现如下错误
摘录:
self._handle = _dlopen(self._name, mode)
OSError: dlopen(./foo.so, 6): Symbol not found: _caml_code_area_end
完全错误:
Traceback (most recent call last):
File "foo.py", line 3, in <module>
lib = ctypes.cdll.LoadLibrary('./foo.so')
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ctypes/__init__.py", line 426, in LoadLibrary
return self._dlltype(name)
File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ctypes/__init__.py", line 348, in __init__
self._handle = _dlopen(self._name, mode)
OSError: dlopen(./foo.so, 6): Symbol not found: _caml_code_area_end
Referenced from: ./foo.so
Expected in: flat namespace
in ./foo.so
我在编译器目录ocamlopt -where 中四处寻找符号。
$ find `ocamlopt -where` | xargs -I% bash -c 'nm % | sed -e "s|^|%:|"' | & grep _caml_code_area_end
/usr/local/lib/ocaml/libasmrun_pic.a: 0000000000000008 C _caml_code_area_end
/usr/local/lib/ocaml/libasmrun_pic.a: U _caml_code_area_end
/usr/local/lib/ocaml/libasmrunp.a: 0000000000000008 C _caml_code_area_end
/usr/local/lib/ocaml/libasmrunp.a: U _caml_code_area_end
/usr/local/lib/ocaml/libasmrun_shared.so: 000000000001ded0 S _caml_code_area_end
/usr/local/lib/ocaml/libasmrun.a: 0000000000000008 C _caml_code_area_end
/usr/local/lib/ocaml/libasmrun.a: U _caml_code_area_end
/usr/local/lib/ocaml/libasmrund.a: 0000000000000008 C _caml_code_area_end
/usr/local/lib/ocaml/libasmrund.a: U _caml_code_area_end
并尝试先加载/usr/local/lib/ocaml/libasmrun_shared.so,给
import ctypes
lib = ctypes.cdll.LoadLibrary('/usr/local/lib/ocaml/libasmrun_shared.so')
lib = ctypes.cdll.LoadLibrary('./foo.so')
print("Loaded")
产生错误的原因:
OSError: dlopen(/usr/local/lib/ocaml/libasmrun_shared.so, 6): Symbol not found: _caml_apply2
Referenced from: /usr/local/lib/ocaml/libasmrun_shared.so
Expected in: flat namespace
in /usr/local/lib/ocaml/libasmrun_shared.so
_caml_apply2 符号在 OCaml 的运行时中很深,我无法为它找到带有 .so 扩展名的文件...而 cdll 似乎没有公开以下功能加载.as.
【问题讨论】: