在 OCaml 库中仅运行一次代码
我正在编写一个 OCaml 库,其中包含一些初始化代码,这些代码在使用该库的程序的生命周期内只需要运行一次(并存储一些将在程序的生命周期中持续存在的状态,但只能在库本身内使用),以及一些仅在使用该库的程序退出时才需要运行的清理代码。
如果相关的话,我的库由两部分组成:低级 C 库的接口,以及一些使编程更容易的高级内容。我可以在 C 的某个地方做我需要的事情吗?理想情况下,我的用户不会关心它是如何实现的,他们永远不会看到 C 位。
在 Python 中,我会通过在 import
上运行代码来实现此目的,但 OCaml 的 open
实际上并不运行任何东西,它只是对模块命名空间进行糖化处理,然后是 Python 的 atexit< /code>,但我找不到 Ocaml 等效项。
我考虑过的一种方法是将我的库构建为一个“框架”,但我认为它的重要性不足以保证这种过度设计的方法。谢谢!
更新:好的,我想明白了。我正在使用 C 代码来处理退出时的清理,并且我对代码进行了一些修改,因此在 C 端有一个指向全局状态的指针,
它会出现在我的库中,我现在 ?
let global_env = env_create ()
当主程序打开
时,它确实运行...但是如何运行呢
I am writing an OCaml library that has some initialization code that needs to be run only once during the lifetime of the program using the library (and store some state that will persist for the lifetime of the program, but only be used within the library itself), and some cleanup code that needs to be run only as the program using the library exits.
If it is relevant, my library is two parts: an interface to a low-level C library, and some higher-level stuff to make programming with it easier. Can I do what I need somewhere in the C? Ideally my users wouldn't care how it was implemented, they would never see the C bits.
In Python I would do this by running code on import
but OCaml's open
doesn't actually run anything, it just sugars the module namespace, and then Python's atexit
, but I can't find the Ocaml equivalent.
One approach I have considered is structuring my library as a "framework" but I don't think it's important enough to warrant such an over-engineered approach. Thanks!
UPDATE: OK got it - I think. I am using the C code to handle the cleanup on exit and I have monkeyed with the code a bit so there is a pointer to the global state on the C side
It would appear that in my library I now have
let global_env = env_create ()
And when it is open
'd by the main program, this does get run... But how?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
请注意,这可以在 OCaml 端使用
Pervasives.at_exit
和顶级语句来创建环境并安装清理代码:顶级语句在模块加载(无论您最终是否使用)和模块加载时执行按照您在链接时指定的顺序(因此依赖于其他模块的模块可以保证在轮到它们时初始化它们的依赖项),请参阅 ocamlc 手册。这意味着顶级语句将在您尝试访问模块之前执行。这不是打开模块的问题,
open
只是一种(糟糕的)语法便利。如果您希望当且仅当模块的函数最终被调用时才执行初始化代码,请使用惰性值:
顺便说一句。不要忘记记录线程安全所产生的问题......
Note that this can be done on the OCaml side with
Pervasives.at_exit
and top-level statements to create the environment and install the cleanup code :The toplevel statements are executed when the module is loaded (whether you eventually use it or not) and modules are loaded in the order you specified them at link time (thus modules depending on others are guaranteed that their dependencies are initialized when their turn comes), see "Arguments ending with .cmo" in the manual of ocamlc. This entails that toplevel statements will have executed before you try to access the module. It's not a matter of opening the module,
open
is just a (bad) syntactic convenience.If you want the init code to be performed if and only if a function of the module eventually gets called use a lazy value :
Btw. don't forget to document the resulting issues with thread-safety...
正如
let x = function ...
定义了一个从该点可用的函数x
从此以后,您的
let global_env = ...
定义了一个值global_env
。如果你不这样做需要
env_create
的返回值,因为您运行它只是为了它的副作用,你也可以在末尾(说实话,任何地方)提到
env_create ()
ml 文件。
在这种情况下,我会执行
let _ = env_create ()
,我认为这更明确。编辑:R指出以下是错误的:
“要纯粹用 C 语言实现,我认为
_init
和_fini
是需要寻找的东西。”正如HOWTO中所解释的,它确实已被弃用,现在应该完成通过属性。
Just as
let x = function ...
defines a functionx
that is available from that pointonwards, your
let global_env = ...
defines a valueglobal_env
that is. If you don'tneed the return value of
env_create
, because you run it only for it's side effects,you could also just mention
env_create ()
at the end (to be honest, anywhere) of theml file.
In this case I would do
let _ = env_create ()
though, which I think is more explicit.EDIT: R pointed out that the following is wrong:
"To do it purely in C, I think that
_init
and_fini
are the things to look for."As explained in this HOWTO, it is indeed deprecated and should now be done via attributes.