我正在尝试使用Dynlink动态加载OCaml模块。我写了一个非常简单的测试程序,但它没有用。
此测试程序包含两个模块,即Plug和Ext。插头是“主要”模块。它知道Ext的文件名并用Dynlink.loadfile
加载它。 Ext引用插件,并在Plug中调用一个函数,告知Plug其中一个函数,以便可以调用它。在Plug加载Ext之后,它调用Ext应该注册的函数。
如果我写它,Ext模块加载成功,这样它就不会执行任何代码。但是,如果我将包含扩展函数的部分包含在Plug中,那么我会收到错误:The module 'Plug' is not yet initialized
。
我不明白Plug是如何初始化的,因为它已经在执行。 (实际上我不知道OCaml模块初始化意味着什么。)
我已将代码缩减到几乎没有必要重现问题。我在Linux上使用OCaml 4.01.0。
这是主要模块:
(* plug.ml *)
type xfn = string -> unit
let dummy_func str =
print_endline ("Dummy: " ^ str)
let ext_func : xfn ref = ref dummy_func
let register func =
ext_func := func
let call () =
(!ext_func) "calling"
(* load extension *)
let () =
try
print_endline "Loading ext.";
Dynlink.loadfile "ext.cmo";
print_endline "Loaded ext.";
()
with
| Dynlink.Error e ->
print_endline (Dynlink.error_message e);
print_endline "Calling registered func.";
call ()
这是扩展档案:
(* ext.ml *)
open Plug
let myext str =
print_endline ("Ext: " ^ str)
let () = Plug.register myext
我使用这个shell脚本来编译可执行文件:
#!/bin/sh
ocamlc -c plug.ml && \
ocamlc -c ext.ml && \
ocamlc -o plug dynlink.cma plug.cmo ext.cmo \
|| exit 1
这是我得到的输出:
Loading ext.
error while linking ext.cmo.
The module `Plug' is not yet initialized
Calling registered func.
Dummy: calling
答案 0 :(得分:2)
在这种情况下,看起来我没有使用我的搜索引擎技能。
更多挖掘出现了一个存档的电子邮件链,该链表明在动态加载的模块可以调用之前,必须已完全评估引用的模块(在这种情况下为Plug
)。
解决方案是将加载扩展模块的代码和扩展模块调用的代码分成两个独立的模块(所以现在总共有三个模块)。