Call rb_instance_eval from C code

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.

Hi, Victor.

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

_why

···

On Tue, Jun 06, 2006 at 02:16:31AM +0900, Victor Shepelev 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) ?

I don't think that will work: proc is not a String but a Proc (TypeError).

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

···

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

On Tue, Jun 06, 2006 at 02:16:31AM +0900, Victor Shepelev 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);

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

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

···

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

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

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

Thanks why! Would try this.

Victor.

···

From: why the lucky stiff [mailto:ruby-talk@whytheluckystiff.net]
Sent: Monday, June 05, 2006 11:40 PM

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:

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:

···

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

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

Behalf Of Mauricio Fernandez

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

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>

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.

···

From: Mauricio Julio Fernandez Pradier [mailto:ferferse@telefonica.net] On
Sent: Wednesday, June 07, 2006 2:15 PM

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: