【问题标题】:How do I convert a Block to a Proc in a Ruby 1.9 C extension?如何在 Ruby 1.9 C 扩展中将 Block 转换为 Proc?
【发布时间】:2012-02-12 17:50:50
【问题描述】:

我正在编写一个 Ruby 1.9 C 扩展,我想在 ruby​​ 中执行以下操作:

notifier = Notifier.new
notifier.on 'click' do
  puts "clicked!"
end

现在的问题是,在 C 方法上,我只“接收”一个块,据我所知,它甚至不是参数:我可以用 rb_yield 调用。

所以我的问题是:Ruby 1.9 C 扩展有没有办法将块转换为 proc 或其他东西,所以我可以将它存储在我的模块中,并在以后需要时调用它?就像一个异步回调!

我已经用 Procs/lambdas 实现了这个,但是不直接使用块语法实在是太丑了。

【问题讨论】:

  • 你看过this的文章(尤其是“显式块”段落)吗?它可能已经过时,但它看起来就像您需要的一样。
  • 对不起,我无法回答你的问题,因为我不知道 C 和 YARV C API,但作为对其他读者的澄清,你的问题基本上是:“我该怎么做@ 987654324@来自C",对吧?

标签: c ruby block ruby-1.9 ruby-c-extension


【解决方案1】:

在 Ruby C 源代码中,您将在 proc.c 中看到这一点:

/*
 * call-seq:
 *   proc   { |...| block }  -> a_proc
 *
 * Equivalent to <code>Proc.new</code>.
 */

VALUE
rb_block_proc(void)
{
    return proc_new(rb_cProc, FALSE);
}

Proc.new 这样做:

创建一个新的Proc 对象,绑定到当前上下文。 Proc::new 只能在带有附加块的方法中调用而没有块,在这种情况下,该块将转换为 Proc 对象。

所以你会做这样的事情:

VALUE p = rb_block_proc();
/* and then store `p` somewhere convenient */

然后再调用块/过程:

rb_funcall(p, rb_intern("call"), 0);

rb_funcall 几乎是 p.send(:call) 的 C 版本。

【讨论】:

  • @rubenfonseca:一旦你知道该怎么做就很简单 :) 你需要对 C 源代码有足够的了解才能编写 C 扩展。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多