Calling instance_eval on a block in C

If I have this ruby method:

def eval_it(obj, &b)
  obj.instance_eval(&b)
end

How do write the C code to make this happen? If I do this:

rb_funcall(obj, rb_intern("instance_eval"), 1, zz);

Ruby is apparently expecting a String for the type of zz.

Any ideas?

Thanks!
-John
http://www.iunknown.com

Hey John,

I'm not positive, but I don't think it is possible, because of the block. Blocks come in through manipulated ruby_frames, even if they look like they are passed in via shells. Clues being:

static VALUE
rb_f_block_given_p()
{
     if (ruby_frame->prev && ruby_frame->prev->iter == ITER_CUR && ruby_block)
         return Qtrue;
     return Qfalse;
}

and the first hunk of specific_eval reading:

     if (rb_block_given_p()) {
         if (argc > 0) {
             rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc\
);
         }
         return yield_under(klass, self);
     }

···

On Apr 14, 2006, at 10:33 AM, John Lam wrote:

If I have this ruby method:

def eval_it(obj, &b)
  obj.instance_eval(&b)
end

How do write the C code to make this happen? If I do this:

rb_funcall(obj, rb_intern("instance_eval"), 1, zz);

Ruby is apparently expecting a String for the type of zz.

def eval_it(obj, &b)
  obj.instance_eval(&b)
end

moulon% cat a.c
#include <ruby.h>

static VALUE
a_eval_it(VALUE obj, VALUE a)
{
    return rb_obj_instance_eval(0, 0, a);
}

void Init_a()
{
    VALUE a_cA = rb_define_class("A", rb_cObject);
    rb_define_method(a_cA, "eval_it", a_eval_it, 1);
}
moulon%

moulon% ruby -ra -e 'b = Object.new; A.new.eval_it(b) {p self; @b = 12}; p b'
#<Object:0xb7d5ec8c>
#<Object:0xb7d5ec8c @b=12>
moulon%

Guy Decoux

I think you're right. I've tried all sorts of combinations before posting
this plea for help :slight_smile:

Now I have to turn this method that I've been writing all morning inside-out
since I can't make this happen ... yuck.

Thanks for looking around!
-John

Hey John,

···

I'm not positive, but I don't think it is possible, because of the
block. Blocks come in through manipulated ruby_frames, even if they
look like they are passed in via shells. Clues being:

static VALUE
rb_f_block_given_p()
{
     if (ruby_frame->prev && ruby_frame->prev->iter == ITER_CUR &&
ruby_block)
         return Qtrue;
     return Qfalse;
}

and the first hunk of specific_eval reading:

     if (rb_block_given_p()) {
         if (argc > 0) {
             rb_raise(rb_eArgError, "wrong number of arguments (%d
for 0)", argc\
);
         }
         return yield_under(klass, self);
     }

See [ruby-talk:180647].

···

On Sat, Apr 15, 2006 at 03:02:55AM +0900, Ryan Davis wrote:

On Apr 14, 2006, at 10:33 AM, John Lam wrote:
>If I have this ruby method:
>
>def eval_it(obj, &b)
> obj.instance_eval(&b)
>end
>
>How do write the C code to make this happen? If I do this:
>
>rb_funcall(obj, rb_intern("instance_eval"), 1, zz);
>
>Ruby is apparently expecting a String for the type of zz.

I'm not positive, but I don't think it is possible, because of the
block.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

THANK YOU!!!!!!

You have saved me from probably a good week's worth of hell (aka C++). I
spent a lot of time building up my abstractions in RubyCLR so that all of
the nasty marshaling / interop goo generation stuff was handled in Ruby.
Without your solution, I would have had to re-implement about half of those
abstractions in raw C++, which probably would have taken me at least another
week to implement.

Let me know if we're ever in the same city - I definitely owe you dinner for
this one :slight_smile:

Cheers,
-John

···

On 4/15/06, ts <decoux@moulon.inra.fr> wrote:

> def eval_it(obj, &b)
> obj.instance_eval(&b)
> end

moulon% cat a.c
#include <ruby.h>

static VALUE
a_eval_it(VALUE obj, VALUE a)
{
    return rb_obj_instance_eval(0, 0, a);
}

void Init_a()
{
    VALUE a_cA = rb_define_class("A", rb_cObject);
    rb_define_method(a_cA, "eval_it", a_eval_it, 1);
}
moulon%

moulon% ruby -ra -e 'b = Object.new; A.new.eval_it(b) {p self; @b = 12}; p
b'
#<Object:0xb7d5ec8c>
#<Object:0xb7d5ec8c @b=12>
moulon%

Guy Decoux