On Sat, May 18, 2002 at 09:58:10AM +0900, Joel VanderWerf wrote:
> Does anyone know an efficient way to call instance_eval from C? I'm
> currently using 

instance_eval takes a block, not a proc.  So you need to use rb_iterate:

  VALUE my_instance_eval(VALUE obj) {
      return rb_funcall(obj, rb_intern("instance_eval"), 0);
  }

  VALUE my_call_proc(VALUE yield_args, VALUE proc) {
      if(rb_obj_is_kind_of(yield_args, rb_cArray)) {
          return rb_funcall2(
              proc,
              rb_intern("call"),
              RARRAY(yield_args)->len,
              RARRAY(yield_args)->ptr);
      } else {
          return rb_funcall2(
              proc,
              rb_intern("call"),
              1,
              &yield_args);
      }
  }

  VALUE foo(VALUE self, VALUE obj, VALUE proc) {
      return rb_iterate(my_instance_eval, obj, my_call_proc, proc);
  }

Then in your Ruby code, something like:

  foo(Foo, proc { p self })

I do have a couple of questions about this, though:

  1) If I try to call rb_instance_eval from my_instance_eval, then I get
     "yield called out of block" (or a similar error, depending on my
     ruby version).  Is it possible to call rb_obj_instance_eval
     directly?  (The same applies for rb_yield, which the pickaxe book
     says I should be able to call from within my_instance_eval).

  2) Is there a better way to write my_call_proc?  It seems somewhat
     awkward, imo.

Hope this helps,

Paul