7

我正在使用 NativeCall 接口。

该库将多次调用我的回调函数。

这很好用。我可以用正确的签名声明我的回调,将它作为 &callback 传递,然后库调用 sub 就好了。

它还能够将有效负载 void *pointer 设置为我想要的任何内容,并将其包含在对我的回调函数的调用中。

例如,我可以在有效负载中隐藏一个 Perl Str 并成功往返吗?

sub set_userdata(Pointer) returns int32 is native { ... }

sub set_callback(&callback(Pointer $userdata --> int32)) returns int32 is native { ... }

sub callback(Pointer $userdata) returns int32 {
    my Str $mystring = ???
    ...
}

my Str $my-userdata-string;

set_userdata(???);
set_callback(&callback);

似乎它可以与一些绑定咒语一起使用,“is rw”,nativecast() 和/或 .deref。

4

2 回答 2

9

在这种情况下,您只能使用原生表示(例如CStructCArrayCPointer),或者使用Blob. 从 Perl 6 的角度来看,您还负责确保对您传递的事物的引用保持为userdata活动状态,因此 GC 不会回收传递给 C 函数的内存。

内存管理是您不能将任何旧的 Perl 6 对象传递给 C 函数的原因:GC 无法通过无法自省的某些 C 数据结构知道该对象是否仍可访问。在像 MoarVM 这样的 VM 中,对象也会随着时间的推移在内存中移动,这也是垃圾收集过程的一部分,这意味着 C 代码最终可能会得到一个过时的指针。

另一种策略是根本不传递指针,而是传递一个整数并使用它来索引对象数组。(这就是 MoarVM 内部的 libuv 绑定跟踪 VM 级回调的方式,fwiw。)

于 2017-04-13T20:34:20.790 回答
3

我通过忽略用户数据并为每个回调函数直接引用 Perl 对象的新闭包来解决这个问题。由于每次设置回调时都会创建一个新的闭包,我认为这会随着时间的推移而泄漏内存。

于 2017-04-13T13:23:58.337 回答