2009-08-06 7 views
1

Ruby Cの拡張モジュールにprocsの配列を格納していますが、各procを経由してinstance_evalを実行する必要があります。問題は、instance_evalはprocsではなくブロックのみを受け入れることです。これは私が単純に行くことができるRubyの問題ではありません:ProcをRuby C拡張モジュールのブロックに変換するにはどうすればよいですか?

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

しかし私はRuby C APIを使ってこれについてどうやって行くのか分かりません。

私はこれをどのように達成するか考えている人はいますか?

答えて

1

ピクサクセ、p。 871(1.9版)

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

引数引数とブロックブロックでメソッドを呼び出します。 A yieldからその メソッドはyieldに与えられた引数と第2の 引数arg2でblockを呼び出します。

だから、arg2としてあなたProcオブジェクトを渡すだけProc#callメソッドに渡された値を転送(*block)()関数を定義します。

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); 
} 

よう

何か私はこのコードをテストしていませんが、それはthis articleにおける注意点と一致します。

+0

私はこれが私が望むものであるとは確信していません。 README.EXT見: VALUEのrb_iterate(VALUE(*関数func1)()、ボイド* ARG1、VALUE(*関数func2)()、ボイド * ARG2) ブロックとして関数func2を供給する、関数func1のを呼び出します。 func1は引数arg1で呼び出される になります。 func2はyieldから という値を受け取り、最初の引数arg2を2番目の引数として受け取ります。 値rb_yield(VALUE val) 値valを持つブロックを評価します。 rb_iterate()はブロック引数として別のC関数を使用できるように見えますが、実際にはブロック引数としてPROCが必要です。私はブロックの引数としてそれを必要とするので、私はrb_obj_instance_evalそれを行うことができます:) – horseyguy

+0

私は上記のように、あなたはargc2として渡すProcの#呼び出しを呼び出して渡すCの関数を持っている。 – rampion

+0

しかし、Proc#呼び出しはinstance_evalではありません!私は特定のオブジェクトのコンテキストでProcを評価する必要があります! あなたが言ったことは、proc_list.each {| p | p.call} が必要ですが、私はproc_list.each {| p | receiver.instance_eval(&p)} – horseyguy

関連する問題