如何通过 Nativecall 回调传递 Perl 6 对象?
How can I pass a Perl 6 object through a Nativecall callback?
我正在使用 NativeCall 界面。
库将多次调用我的回调函数。
效果很好。我可以用正确的方式声明我的回调
签名,将其作为 &callback 传入,库仅调用 sub
很好。
它也有能力设置一个 payload 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() and/or .deref.
我通过忽略用户数据并为每个回调函数创建一个直接引用 Perl 对象的新闭包来解决这个问题。由于每次设置回调都会创建一个新的闭包,我认为这会随着时间的推移而泄漏内存。
在这种情况下您只能使用本机表示(例如 CStruct
、CArray
和 CPointer
),或者 Blob
。您还负责确保从 Perl 6 的角度来看,您还保留对作为 userdata
传递的内容的引用,因此 GC 不会回收传递给 C 函数的内存。
内存管理是您不能将任何旧的 Perl 6 对象传递给 C 函数的原因:GC 无法知道该对象是否仍然可以通过它无法自省的某些 C 数据结构访问.在像 MoarVM 这样的 VM 中,对象也会随着时间的推移在内存中移动,这也是垃圾收集过程的一部分,这意味着 C 代码可能会以过时的指针结束。
另一种策略是根本不传递指针,而是传递一个整数并使用它来索引对象数组。 (这就是 MoarVM 内部的 libuv 绑定如何跟踪 VM 级回调,fwiw。)
我正在使用 NativeCall 界面。
库将多次调用我的回调函数。
效果很好。我可以用正确的方式声明我的回调 签名,将其作为 &callback 传入,库仅调用 sub 很好。
它也有能力设置一个 payload 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() and/or .deref.
我通过忽略用户数据并为每个回调函数创建一个直接引用 Perl 对象的新闭包来解决这个问题。由于每次设置回调都会创建一个新的闭包,我认为这会随着时间的推移而泄漏内存。
在这种情况下您只能使用本机表示(例如 CStruct
、CArray
和 CPointer
),或者 Blob
。您还负责确保从 Perl 6 的角度来看,您还保留对作为 userdata
传递的内容的引用,因此 GC 不会回收传递给 C 函数的内存。
内存管理是您不能将任何旧的 Perl 6 对象传递给 C 函数的原因:GC 无法知道该对象是否仍然可以通过它无法自省的某些 C 数据结构访问.在像 MoarVM 这样的 VM 中,对象也会随着时间的推移在内存中移动,这也是垃圾收集过程的一部分,这意味着 C 代码可能会以过时的指针结束。
另一种策略是根本不传递指针,而是传递一个整数并使用它来索引对象数组。 (这就是 MoarVM 内部的 libuv 绑定如何跟踪 VM 级回调,fwiw。)