2012-01-17 17 views
6

私はRuby 1.9のC拡張を書いていると私はルビーで次の操作を実行したい:、ブロックをRuby 1.9 C拡張モジュールのProcに変換するにはどうすればよいですか?

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

さて、これで問題はC法に、私は唯一のブロックを「受け取る」ということで、私が知る限り、それはパラメータではない:私はちょうどrb_yieldと呼ぶことができる。

Ruby 1.9 C拡張モジュールを使ってブロックをprocなどに変換する方法があるので、モジュール内に格納して後で呼び出すことができます。非同期コールバックのように!

私はすでにこれをProcs/lambdasで実装しましたが、ブロック構文を直接使用するのは面倒です。

+5

[this](http://banisterfiend.wordpress.com/2008/09/25/metaprogramming-in-the-ruby-c-api-part-one-blocks/)の記事(特に「明示的ブロック "段落)?それは時代遅れかもしれないが、そうでなければあなたが必要とするもののように見える。 –

+0

申し訳ありませんが、私はCやYARV C APIを知らないので、私はあなたの質問に答えることができませんが、他の読者への説明として、あなたの質問は基本的には: "def on(&blk)end' Cから "、右? –

答えて

5

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オブジェクトに変換されます。 rb_funcallはかなりのCバージョンであることを

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

ですから、このような何かしたい:、後でそのブロックを呼び出すために/ procを

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

をし、 p.send(:call)

+0

ああ私の神はとてもシンプルでクリアだった!ありがとうございました! – rubenfonseca

+0

@rubenfonseca:あなたが何をすべきかを知っていれば簡単です:) C拡張を書くには、Cソースの習熟度が必要です。 –

関連する問題