From: Joel VanderWerf Date: 2004-05-03T08:00:10+09:00 Subject: Re: instance_eval from C ext Mauricio Fern�ndez wrote: > On Mon, May 03, 2004 at 03:10:24AM +0900, Joel VanderWerf 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 #include 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); }