4

我正在编写一个 OCaml 库,它有一些初始化代码,在使用该库的程序生命周期内只需要运行一次(并存储一些将在程序生命周期内持续存在的状态,但只能在库本身中使用),以及一些仅在使用该库的程序退出时才需要运行的清理代码。

如果它是相关的,我的库是两部分:一个低级 C 库的接口,以及一些更高级的东西,使编程更容易。我可以在 C 的某个地方做我需要的事情吗?理想情况下,我的用户不会关心它是如何实现的,他们永远不会看到 C 位。

在 Python 中,我会通过运行代码来做到这一点,import但 OCamlopen实际上并没有运行任何东西,它只是对模块命名空间加糖,然后是 Python 的atexit,但我找不到 Ocaml 的等价物。

我考虑过的一种方法是将我的库构建为一个“框架”,但我认为这不足以保证这种过度设计的方法。谢谢!

更新:好的,我想。我正在使用 C 代码来处理退出时的清理,并且我对代码进行了一些修改,因此在 C 端有一个指向全局状态的指针

看来,我的图书馆里,我现在有

let global_env = env_create ()

当它被open主程序运行时,它确实会运行......但是如何?

4

2 回答 2

7

请注意,这可以在 OCaml 端使用Pervasives.at_exit顶级语句来创建环境并安装清理代码:

let env = init ()
let cleanup () = do_clean env
let () = at_exit cleanup 

let f x = f_stub env x

顶级语句在模块加载时执行(无论您最终是否使用它)并且模块按照您在链接时指定的顺序加载(因此依赖于其他模块的模块保证在轮到它们时初始化它们的依赖项) ,请参阅ocamlc 手册中的“以 .cmo 结尾的参数” 。这需要在您尝试访问模块之前执行顶级语句。这不是打开模块的问题,open只是一种(不好的)语法便利。

如果您希望当且仅当模块的函数最终被调用时才执行初始化代码,请使用惰性值:

let env = lazy (init ())
let cleanup () = if Lazy.lazy_is_val env then (do_clean env) else () 
let () = at_exit cleanup

let f x = f_stub (Lazy.force env) x

顺便提一句。不要忘记用线程安全记录由此产生的问题......

于 2011-05-06T14:26:36.680 回答
1

正如定义从那时起可用let x = function ...的函数一样,您定义的值就是。如果您不需要 的返回值,因为您运行它只是为了它的副作用,您也可以在 ml 文件的末尾(老实说,任何地方)提及。在这种情况下,我会这样做,我认为这更明确。xlet global_env = ...global_envenv_createenv_create ()let _ = env_create ()

编辑:R 指出以下错误:“纯粹在 C 中做,我认为这是要寻找的东西。_init_fini正如本HOWTO中所解释的,它确实已被弃用,现在应该通过属性来完成。

于 2011-05-06T11:53:18.410 回答