如何将 Proc 转换为 Ruby C 扩展中的块?

发布于 2024-07-29 21:55:18 字数 274 浏览 8 评论 0原文

我在 Ruby C 扩展中存储了一个过程数组,我需要遍历每个过程并对每个过程进行实例评估。 问题是instance_eval只接受块,而不接受过程。 这不是 Ruby 中的问题,我可以简单地解决这个问题:

proc_list.each { |my_proc|
    @receiver.instance_eval(&my_proc)
}

但是我不确定如何使用 Ruby C API 来解决这个问题。

有谁知道我如何实现这一目标?

I am storing an array of procs in a Ruby C extension and I need to go through and instance_eval each proc. The problem is that instance_eval only accepts blocks, not procs. This is not an issue in Ruby where I can simply go:

proc_list.each { |my_proc|
    @receiver.instance_eval(&my_proc)
}

However I am unsure how to go about this using the Ruby C API.

Does anyone have any ideas how I might accomplish this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

他夏了夏天 2024-08-05 21:55:22

从镐,p。 871(1.9版)

VALUE rb_iterate( VALUE (*method)(), VALUE args, VALUE (*block)(), VALUE arg2 )

使用参数 args 和块 block 调用方法。 从中获得的收益
方法将使用给定的参数调用 block 和第二个
参数 arg2。

因此,将您的 Proc 对象作为 arg2 传递,并定义一个 (*block)() 函数,该函数仅将传递的值转发到 Proc#call 方法。

就像

for (i = 0; i < numProcs; i++)
{
  rb_iterate( forwarder, receiver, block, procs[i] );
}

/*...*/

VALUE forwarder(VALUE receiver)
{
  // the block passed to #instance_eval will be the same block passed to forwarder
  return rb_obj_instance_eval(0, NULL, receiver);
}
VALUE block(VALUE proc)
{
  return rb_funcall(proc, rb_intern("call"), 0);
}

我还没有测试过这段代码,但它与 这篇文章

From the pickaxe, p. 871 (1.9 edition)

VALUE rb_iterate( VALUE (*method)(), VALUE args, VALUE (*block)(), VALUE arg2 )

Invokes method with argument args and block block. A yield from that
method will invoke block with the argument given to yield and a second
argument arg2.

So pass your Proc objects as arg2 and define a (*block)() function that just forwards the passed value to the Proc's #call method.

Something like

for (i = 0; i < numProcs; i++)
{
  rb_iterate( forwarder, receiver, block, procs[i] );
}

/*...*/

VALUE forwarder(VALUE receiver)
{
  // the block passed to #instance_eval will be the same block passed to forwarder
  return rb_obj_instance_eval(0, NULL, receiver);
}
VALUE block(VALUE proc)
{
  return rb_funcall(proc, rb_intern("call"), 0);
}

I haven't tested this code, but it's consistent with the caveats in this article.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文