2009-08-06 53 views
1

我在一个Ruby C扩展中存储了一个proc数组,我需要通过和instance_eval每个proc。问题是,instance_eval只接受块,而不是proc。这是不是在Ruby的一个问题,我可以简单地去:如何将Proc转换为Ruby C扩展中的块?

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

但是我不确定如何去这个使用Ruby C API。

有没有人有任何想法,我可能会做到这一点?

回答

1

从镐,页。 871(1.9版)

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

调用方法用参数指定参数和块的块。来自 方法的yield将调用带给出的参数的块和第二个参数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); 
} 

我还没有测试此代码,但它是在this article的告诫是一致的。

+0

我不确定这是我想要的;看着README.EXT: VALUE rb_iterate(VALUE(* func1的)(),无效* ARG1,VALUE(* FUNC2)(),空隙 * ARG2) 调用函数func1的,供给FUNC2作为块。 func1将被 用参数arg1调用。 func2从yield中得到的值为 第一个参数,arg2作为第二个参数。 VALUE rb_yield(VALUE val) 用值val计算块。 所以看来,rb_iterate()让我使用另一个C函数作为块参数,但我实际上需要一个PROC作为块参数。我需要它作为一个块arg,所以我可以rb_obj_instance_eval :) :) – horseyguy 2009-08-10 19:46:27

+0

就像我上面说过的那样,你传递的C函数只是调用Proc#对你传递的proc#调用arg2。 – rampion 2009-08-10 20:12:24

+0

但是一个Proc#调用不是一个instance_eval!我需要在特定对象的语境中评估Proc! 你所说的相当于proc_list.each {| p | p.call} 但我需要proc_list.each {| p | receiver.instance_eval(&p)} – horseyguy 2009-08-10 20:52:52