Reputation: 29915
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?
Upvotes: 1
Views: 817
Reputation: 89093
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.
Upvotes: 1