【问题标题】:How can I pass a Perl 6 object through a Nativecall callback?如何通过 Nativecall 回调传递 Perl 6 对象?
【发布时间】:2017-04-12 13:24:13
【问题描述】:

我正在使用 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。

【问题讨论】:

  • 没有接受的答案,希望 OP 可以帮助读者了解以下哪些答案是/最有用的。谢谢。

标签: raku nativecall


【解决方案1】:

您只能在这种情况下使用本机表示(例如CStructCArrayCPointer),或者Blob。从 Perl 6 的角度来看,您还负责确保对作为 userdata 传递的内容的引用保持有效,因此 GC 不会回收传递给 C 函数的内存。

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

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

【讨论】:

  • 我喜欢在 Perl 端管理的静态数组中建立索引的想法。然后一个回调就可以抓住正确的对象。谢谢!
【解决方案2】:

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

【讨论】:

  • 尽管 Jonathan Worthington 提出了一种更好的方法,但我认为在这个答案中看到一个简短的尝试示例会很酷,因为人们可以讨论您的解决方案是否有价值,以及是否确实如此泄漏内存。毕竟这是一个学习网站。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
相关资源
最近更新 更多