OCaml 编译 &运行时加载 [英] OCaml compile & load during run-time

查看:39
本文介绍了OCaml 编译 &运行时加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 OCaml 中实现类似于 eval() 的东西.

I am trying to achieve something similar to eval() in OCaml.

我有一个 string 并且我想从中得到一个 OCaml 函数.目前我正在做以下事情:

I have a string and I want to get an OCaml function out of it. Currently I am doing the following:

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

I dump the string to new.ml and compile the file:

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

然后我尝试dynlink文件:

Dynlink.loadfile "new.cmo";

但是如果我尝试执行 New.foo 它会失败.我不知道为什么在 Dynlinking 之后我无法访问模块 New.我错过了什么吗?

But if I try to do New.foo it fails. I am not sure why I cannot access the module New after Dynlinking. Am I missing something?

谢谢!

推荐答案

Dynlink.loadfile 的注释说:

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

No facilities are provided to access value names defined by the unit. Therefore, the unit must register itself its entry points with the main program, e.g. by modifying tables of functions.

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

The loader program cannot access values of dyn-loaded module without any hint, since it has no idea what values are defined in it just from the .cmo file. The dynamic loaded module must register its entry point to some state defined in the loader program.

这是一个最小的例子.一、入口点的模块:

Here is such a minimal example. First, the module for the entry points:

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

加载程序:

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

要动态加载的插件:

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

这里,Plugin 将其函数注册到 Entry.f 中,Entry.f 静态链接到 Loader,这样 Loader> 可以访问该功能.

Here, Plugin registers its function to Entry.f which is statically linked to Loader, so that Loader can access the function.

它们必须按如下方式编译:

They must be compiled as follows:

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

loader.exe 的执行应该演示 dyn 加载是如何工作的:

Execution of loader.exe should demonstrate how the dyn loading works:

$ ./loader.exe
hello world

注意EntryLoader 必须是不同的模块.否则,在动态加载 Plugin 时会出现 Uninitialized_global 异常.动态加载的模块只能访问已经初始化的模块"中的值,当调用 Dynlink.loadfile 时,加载器模块认为自己尚未初始化,因为模块的整个评估还没有完成.

Note that Entry and Loader must be different modules. Otherwise, you get Uninitialized_global exception at dyn-loading Plugin. Dyn-loaded modules can only access values in "already initialized modules", and the loader module thinks itself not yet initialized when Dynlink.loadfile is called, since the entire evaluation of the module is not finished yet.

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

Entry.f is the simplest state to have only one entry point. To dyn-load many values, you may want to have more complicated data structure, such as (string, (unit -> unit)) list ref or (string, (unit -> unit)) Hashtbl.t.

这篇关于OCaml 编译 &运行时加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆