Ocaml 尝试使用Dynlink动态加载模块
我正在尝试使用Dynlink设置OCaml模块的动态加载。我写了一个非常简单的测试程序,但它不起作用 该测试程序由两个模块组成,即插件和扩展模块。插件是“主”模块。它知道Ext的文件名,并使用Ocaml 尝试使用Dynlink动态加载模块,ocaml,Ocaml,我正在尝试使用Dynlink设置OCaml模块的动态加载。我写了一个非常简单的测试程序,但它不起作用 该测试程序由两个模块组成,即插件和扩展模块。插件是“主”模块。它知道Ext的文件名,并使用Dynlink.loadfile加载它。Ext引用Plug,并在Plug中调用一个函数,该函数通知Plug它的一个函数,以便调用它。在Plug加载Ext之后,它调用Ext应该注册的函数 如果我编写Ext模块,使其不执行任何代码,则它将成功加载。但是,如果我将向Plug注册扩展功能的部分包括在内,那么我会得到
Dynlink.loadfile
加载它。Ext引用Plug,并在Plug中调用一个函数,该函数通知Plug它的一个函数,以便调用它。在Plug加载Ext之后,它调用Ext应该注册的函数
如果我编写Ext模块,使其不执行任何代码,则它将成功加载。但是,如果我将向Plug注册扩展功能的部分包括在内,那么我会得到一个错误:模块“Plug”尚未初始化
我不明白为什么插件还不能初始化,因为它已经在执行了。(实际上,我不知道初始化OCaml模块意味着什么。)
我已经将代码缩减到几乎不需要重现问题的程度。我正在Linux上使用OCAML4.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
在这种情况下,我似乎没有掌握搜索引擎技能 进一步挖掘发现了一个存档的电子邮件链,该链指出,在动态加载的模块调用之前,必须对引用的模块(
Plug
)进行完整评估
解决方案是将加载扩展模块的代码和扩展模块调用的代码分离为两个单独的模块(因此现在总共有三个模块)