Forum: Ruby Call rb_instance_eval from C code

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Victor S. (Guest)
on 2006-06-05 21:19
(Received via mailing list)
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.
why the lucky stiff (Guest)
on 2006-06-05 23:14
(Received via mailing list)
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
Mauricio F. (Guest)
on 2006-06-05 23:45
(Received via mailing list)
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].
why the lucky stiff (Guest)
on 2006-06-06 00:43
(Received via mailing list)
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
Victor S. (Guest)
on 2006-06-06 17:51
(Received via mailing list)
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.
Mauricio F. (Guest)
on 2006-06-07 15:18
(Received via mailing list)
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 :)
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 ;)
Victor S. (Guest)
on 2006-06-08 02:04
(Received via mailing list)
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 :) 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 ;)

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

Matz? :)

V.
This topic is locked and can not be replied to.