OCaml编译&在运行时加载

时间:2014-12-10 10:02:04

标签: ocaml

我正在尝试在OCaml中实现与eval()类似的功能。

我有一个string,我希望从中获得一个OCaml功能。 目前我正在做以下事情:

我将字符串转储到new.ml并编译文件:

Compile.implementation Format.std_formatter "new.ml" "New"

然后我尝试dynlink文件:

Dynlink.loadfile "new.cmo";

但如果我尝试New.foo,它就会失败。我不确定为什么在Dynlink之后我无法访问模块New。我错过了什么吗?

谢谢!

1 个答案:

答案 0 :(得分:6)

Dynlink.loadfile的评论说:

  

没有提供任何设施       访问单元定义的值名称。因此,单位       必须在主程序中注册自己的入口点,       例如通过修改函数表。

加载程序无法在没有任何提示的情况下访问dyn-loaded模块的值,因为它不知道仅从.cmo文件中定义了哪些值。动态加载模块必须将其入口点注册到加载程序中定义的某个状态。

这是一个很小的例子。首先,入口点的模块:

(* entry.ml *)
let f : (unit -> unit) ref = ref (fun () -> assert false)

加载程序:

(* loader.ml *)
let () =
    Dynlink.loadfile "plugin.cmo";
    !Entry.f ()

要加载dyn的插件:

(* plugin.ml *)
let () = Entry.f := (fun () -> prerr_endline "hello world")

此处,Plugin将其功能注册到与Entry.f静态链接的Loader,以便Loader可以访问该功能。

必须按如下方式编译:

$ ocamlc -o loader.exe dynlink.cma entry.ml loader.ml
$ ocamlc -c plugin.ml

执行loader.exe应该演示dyn加载的工作原理:

$ ./loader.exe
hello world

请注意,EntryLoader必须是不同的模块。否则,您在dyn-loading Uninitialized_global处获得Plugin异常。加载Dyn的模块只能访问“已初始化的模块”中的值,并且加载器模块在调用Dynlink.loadfile时认为自己尚未初始化,因为模块的整个评估尚未完成。

Entry.f是最简单的状态,只有一个入口点。要对dyn加载许多值,您可能希望拥有更复杂的数据结构,例如(string, (unit -> unit)) list ref(string, (unit -> unit)) Hashtbl.t