如何通过Nativecall回调传递Perl 6对象?

时间:2017-04-12 13:24:13

标签: perl6 nativecall

我正在使用NativeCall界面。

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

工作正常。我可以用右边声明我的回调 签名,将其作为&回调传递,并且库只调用sub 细

它还能够将有效负载void *指针设置为任何东西 我想,它将包含在我的回调函数调用中。

我可以隐藏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);

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

2 个答案:

答案 0 :(得分:8)

您只能在这种情况下使用原生代表(例如CStructCArrayCPointer),或者Blob。您还有责任确保从Perl 6的角度保持对userdata活着的内容的引用,因此GC不会回收传递给C的内存功能

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

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

答案 1 :(得分:3)

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