gpt4 book ai didi

c - 如何复制 OCaml 闭包?

转载 作者:太空狗 更新时间:2023-10-29 15:04:04 34 4
gpt4 key购买 nike

我想存储一个 OCaml 闭包供外部 C 库稍后使用。我能够执行以下操作:

<TARGET> = caml_alloc(Wosize_val(<SOURCE>), Tag_val(<SOURCE>));
caml_register_global_root(<TARGET>);
Code_val(<TARGET>) = Code_val(<SOURCE>);

但是正如名字“闭包”所暗示的那样,仅仅复制代码位置是不够的。

我如何制作(垃圾收集器友好的)副本 <SOURCE>

最佳答案

在我们在 iOS 中使用 OCaml 的工作中,我们经常需要保存 OCaml 闭包并稍后调用它们(当与 CocoaTouch 库交互时)。所以我有已经工作多年的代码。但是,它太复杂了,无法成为一个好的示例(而且它是用 Objective C 编写的)。这是我刚刚编写的一些代码,它们捕获了我们正在做的事情的本质。

首先是一些 C 代码,它保存了一些 unit -> unit 类型的闭包,并允许您稍后按时间顺序调用它们。 (这只是一个例子。)

$ cat saveclo.c
#include "caml/mlvalues.h"
#include "caml/memory.h"
#include "caml/callback.h"

static value saved_closures[10];
static int saved_closure_count = 0;


value save_closure(value clo)
{
CAMLparam1(clo);
saved_closures[saved_closure_count] = clo;
caml_register_global_root(&saved_closures[saved_closure_count]);
saved_closure_count++;
CAMLreturn(Val_unit);
}


value call_closure(value index)
{
CAMLparam1(index);
int ix = Int_val(index);
// For simplicity assume closure : unit -> unit
(void) caml_callback(saved_closures[ix], Val_unit);
CAMLreturn(Val_unit);
}

然后是一些执行这些功能的 OCaml 代码:

$ cat clo.ml
external save_closure : (unit -> unit) -> unit = "save_closure"
external call_closure : int -> unit = "call_closure"

let save alist =
let howlong () =
Printf.printf "list length %d\n" (List.length alist)
in
save_closure howlong

let call () =
call_closure 1;
call_closure 0

let () =
save [1;2;3;4;5];
save ['a'; 'b'; 'c'; 'd'; 'e'; 'f'];
Gc.full_major();
call ()

测试运行如下所示:

$ cc -I /usr/local/lib/ocaml -c -o saveclo.o saveclo.c
$ ocamlopt -c clo.ml
$ ocamlopt -o clo clo.cmx saveclo.o
$ ./clo
list length 6
list length 5
$

我认为重点是 (a) 表示闭包的 OCaml 对象已经包含您需要的内容(某种代码引用和数据)。 (b) 你不需要复制它,你只需要确保它不会被垃圾收集。 (c) 对 caml_register_global_root 的调用创建对闭包的引用,因此 GC 知道不收集它。

希望对您有所帮助。如果有人发现此代码有问题,请告诉我,我将非常乐意纠正错误。但我相信这是正确的。

关于c - 如何复制 OCaml 闭包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23223710/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com