Mauricio Fernández wrote:
Any ideas, anyone? Is this something you can do in ruby, but not using
the C API directly?
Joel VanderWerf wrote:
I’m stumped… how do I call instance_eval from a C extension?
Take a look at
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/86105
you might find it useful.
Well, rb_iterate() is what I was trying before, but apparently it does
not arrange for rb_block_given_p() to be true, and so
rb_obj_instance_eval() bails out. I’ve adapted your example to show how
that is the case in both your code and mine.
The output (ruby-1.9.0 snapshot) is:
foo2, block given = 0
call_gsub, block given = 0
block2, block given = 0
Inside block, with string: h.
block2, block given = 0
Inside block, with string: e.
block2, block given = 0
Inside block, with string: l.
block2, block given = 0
Inside block, with string: l.
block2, block given = 0
Inside block, with string: l.
“HELLo, worLd!”
instance_eval_proc, block given = 0
my_instance_eval, block given = 0
example.rb:11:in `instance_eval_proc’: block not supplied (ArgumentError)
from example.rb:11
So I’m still looking for a solution to my problem, which is: how to
execute a Proc in the context of a given self object, from C code.
In other words, given the following working ruby code:
class Object
def instance_eval_proc(pr)
instance_eval(&pr)
end
end
obj = [1,2,3]
pr = proc { reverse }
p obj.instance_eval_proc(pr) # ==> [3, 2, 1]
how would you rewrite #instance_eval_proc in C?
== extconf.rb ==
require “mkmf”
create_makefile(“example”)
== example.rb ==
require “example.so”
b = “hello, world!”
CTest.foo2(b, /[ehl]/)
p b
obj = [1,2,3]
pr = proc { reverse }
p obj.instance_eval_proc(pr)
== example.c ==
#include <ruby.h>
#include <stdio.h>
VALUE mCTest;
static
VALUE
block2(VALUE str)
{
printf(“block2, block given = %d\n”, rb_block_given_p());
Check_Type(str, T_STRING);
printf(“Inside block, with string: %s.\n”, RSTRING(str)->ptr);
return rb_funcall(str, rb_intern(“upcase”), 0);
}
static
VALUE
call_gsub(VALUE args)
{
VALUE str, re;
printf(“call_gsub, block given = %d\n”, rb_block_given_p());
str = rb_ary_entry(args, 0);
re = rb_ary_entry(args, 1);
return rb_funcall(str, rb_intern(“gsub!”), 1, re);
}
static
VALUE
foo2(VALUE self, VALUE str, VALUE re)
{
VALUE args;
printf(“foo2, block given = %d\n”, rb_block_given_p());
args = rb_ary_new();
rb_ary_push(args, str);
rb_ary_push(args, re);
return rb_iterate(call_gsub, args, block2, str);
}
static VALUE my_instance_eval(VALUE obj)
{
printf(“my_instance_eval, block given = %d\n”, rb_block_given_p());
return rb_obj_instance_eval(0, 0, obj);
}
static VALUE call_block(VALUE arg1, VALUE block)
{
printf(“call_block, block given = %d\n”, rb_block_given_p());
return rb_funcall(block, rb_intern(“call”), 0);
}
static VALUE instance_eval_proc(VALUE self, VALUE pr)
{
printf(“instance_eval_proc, block given = %d\n”, rb_block_given_p());
return rb_iterate(my_instance_eval, self, call_block, pr);
}
void
Init_example()
{
mCTest = rb_define_module(“CTest”);
rb_define_singleton_method(mCTest, “foo2”, foo2, 2);
rb_define_method(rb_cObject, “instance_eval_proc”, instance_eval_proc, 1);
}
···
On Mon, May 03, 2004 at 03:10:24AM +0900, Joel VanderWerf wrote: