Call rb_instance_eval from C code


#1

Hi all.

Assuming I have such C code:

VALUE proc; //contains object of class Proc
VALUE obj; //contains some object

How must look code, corresponding to obj.instance_eval(&proc) ?

Thanks.

V.


#2

On Tue, Jun 06, 2006 at 02:16:31AM +0900, Victor S. wrote:

Assuming I have such C code:

VALUE proc; //contains object of class Proc
VALUE obj; //contains some object

How must look code, corresponding to obj.instance_eval(&proc) ?

Hi, Victor.

rb_funcall(obj, rb_intern(“instance_eval”), 1, proc);

_why


#3

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).

See [ruby-talk:180647] and [ruby-talk:188958].


#4

On Tue, Jun 06, 2006 at 04:43:10AM +0900, Mauricio F. 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).

See [ruby-talk:180647] and [ruby-talk:188958].

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 <ruby.h>

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);
}

VALUE
obj_eval_it(int argc, VALUE *argv, VALUE self)
{
VALUE meth, proc;
rb_scan_args(argc, argv, “0&”, &proc);

  /* !^! here is your rb_instance_eval replacement, victor. !^! */
  meth = rb_proc_bind(self, proc);
  return rb_funcall(meth, rb_intern("call"), 0);

}

void Init_a()
{
VALUE 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);
}

wagon$ ruby -ra -e ‘p Object::OBJ; Object::OBJ.eval_it { @b = 12 }; p
Object::OBJ’
#Object:0x80768dc
#<Object:0x80768dc @b=12>

But now I really don’t understand specific_eval().

_why


#5

From: why the lucky stiff [mailto:removed_email_address@domain.invalid]
Sent: Monday, June 05, 2006 11:40 PM

cloaker.
meta = rb_singleton_class(obj);
rb_scan_args(argc, argv, “0&”, &proc);
rb_const_set(rb_cObject, rb_intern(“OBJ”), obj);
}

wagon$ ruby -ra -e ‘p Object::OBJ; Object::OBJ.eval_it { @b = 12 }; p
Object::OBJ’
#Object:0x80768dc
#<Object:0x80768dc @b=12>

But now I really don’t understand specific_eval().

Thanks why! Would try this.

Victor.


#6

On Tue, Jun 06, 2006 at 05:40:12AM +0900, why the lucky stiff wrote:

wagon$ cat a.c
rb_funcall(meta, rb_intern(“remove_method”), 1, cloaker);
return rb_funcall(meth, rb_intern(“bind”), 1, obj);
}

Nice hack :slight_smile:
Just for fun, here’s another idea:

$ cat ieval.c

#include <ruby.h>

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’
#Object:0xb7e13e14
#<Object:0xb7e13e14 @b=12>

One can still hope matz’s reflection ([180647] again) will bring a more
convenient way to do that, though :wink:


#7

From: Mauricio Julio Fernandez Pradier [mailto:removed_email_address@domain.invalid]
On
Behalf Of Mauricio F.
Sent: Wednesday, June 07, 2006 2:15 PM

cloaker.

  meta = rb_singleton_class(obj);
$ cat ieval.c
}
void Init_ieval()
$ ruby -rieval -e 'p Object::OBJ; Object::OBJ.eval_it { @b = 12 }; p

Object::OBJ’
#Object:0xb7e13e14
#<Object:0xb7e13e14 @b=12>

Thanks Mauricio! Something like this I’ve already invented :slight_smile: Generally,
almost any feature we can’t conveniently use from C, colud be used with
evaluating some string.

One can still hope matz’s reflection ([180647] again) will bring a more
convenient way to do that, though :wink:

It would be the most straightforward way. When it would.

Matz? :slight_smile:

V.