From: Mauricio Fernandez Date: 2006-06-07T20:15:21+09:00 Subject: Re: Call rb_instance_eval from C code On Tue, Jun 06, 2006 at 05:40:12AM +0900, why the lucky stiff wrote: > On Tue, Jun 06, 2006 at 04:43:10AM +0900, Mauricio Fernandez wrote: > > On Tue, Jun 06, 2006 at 04:12:14AM +0900, why the lucky stiff wrote: > > > rb_funcall(obj, rb_intern("instance_eval"), 1, proc); > > > > I don't think that will work: proc is not a String but a Proc (TypeError). > > > > Ohhhh. I guess define_method can take a proc, though. Back to ye olde cloaker. > Based on Guy's example: > > wagon$ cat a.c > #include > > static VALUE > rb_proc_bind(VALUE obj, VALUE a) > { > VALUE meth, meta; > VALUE cloaker = ID2SYM(rb_intern("__cloaker__")); > meta = rb_singleton_class(obj); > rb_funcall(meta, rb_intern("define_method"), 2, cloaker, a); > meth = rb_funcall(meta, rb_intern("instance_method"), 1, cloaker); > rb_funcall(meta, rb_intern("remove_method"), 1, cloaker); > return rb_funcall(meth, rb_intern("bind"), 1, obj); > } Nice hack :) Just for fun, here's another idea: $ cat ieval.c #include static VALUE instance_eval_proc; static VALUE do_instance_eval(VALUE obj, VALUE proc) { return rb_funcall(instance_eval_proc, rb_intern("call"), 2, obj, proc); } VALUE obj_eval_it(int argc, VALUE *argv, VALUE self) { VALUE meth, proc; rb_scan_args(argc, argv, "0&", &proc); return do_instance_eval(self, proc); } void Init_ieval() { VALUE obj; instance_eval_proc = rb_eval_string("lambda{|o,b| o.instance_eval(&b)}"); obj = rb_funcall(rb_cObject, rb_intern("new"), 0); rb_define_method(rb_cObject, "eval_it", obj_eval_it, -1); rb_const_set(rb_cObject, rb_intern("OBJ"), obj); } $ ruby -rieval -e 'p Object::OBJ; Object::OBJ.eval_it { @b = 12 }; p Object::OBJ' # # One can still hope matz's reflection ([180647] again) will bring a more convenient way to do that, though ;) -- Mauricio Fernandez - http://eigenclass.org - singular Ruby