在OCaml库中仅运行一次代码

Gai*_*ius 4 c ocaml native-methods

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

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

在Python中,我会通过运行代码来实现这一点,import但OCaml open实际上并没有运行任何东西,它只是模块化模块命名空间,然后是Python atexit,但我找不到Ocaml等价物.

我考虑过的一种方法是将我的库构建为"框架",但我认为保证这种过度设计的方法并不重要.谢谢!

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

它会出现在我的图书馆我现在有

let global_env = env_create ()
Run Code Online (Sandbox Code Playgroud)

当它open由主程序执行时,它确实可以运行......但是怎么样?

Dan*_*zli 7

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

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

let f x = f_stub env x
Run Code Online (Sandbox Code Playgroud)

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

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

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
Run Code Online (Sandbox Code Playgroud)

顺便说一句.不要忘记用线程安全来记录产生的问题......