instance_eval from C ext

Discussion in 'Ruby' started by Joel VanderWerf, Apr 26, 2004.

  1. I'm stumped... how do I call instance_eval from a C extension?

    I have an object and a proc:

    VALUE obj, pr;

    and I want to eval pr with obj as self.

    Currently, I do something like this, which works, but it's inefficient:

    rb_funcall(obj, rb_intern("insteval_proc"), 1, pr);

    and I have the following defined in ruby:

    class Object
    def insteval_proc pr
    instance_eval &pr
    end
    end

    I'd rather avoid the extra method call.

    It doesn't seem like I can use rb_obj_instance_eval(), because that
    takes string arguments, not block arguments. Of course, if you have a
    block accompanying the method call, it will instance_eval that, but I
    don't know how to set that up in C. That's why I do "instance_eval &pr"
    in my little hack.

    And I can't see how to use rb_iterate(). This is what I tried:


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

    static VALUE call_block(VALUE arg1, VALUE block)
    {
    return rb_funcall(block, ID_call, 0);
    }

    //...
    rb_iterate(my_instance_eval, obj, call_block, pr);


    but I get "block not supplied (ArgumentError)", so I guess it's not
    being propagted into the rb_funcall.

    Is there a simple way to emulate "&block" in C?

    Even better, is there a way to rebind the proc's self to my object, so I
    only have to do it once, and can just call the block instead of using
    instance eval?
    Joel VanderWerf, Apr 26, 2004
    #1
    1. Advertising

  2. Any ideas, anyone? Is this something you can do in ruby, but not using
    the C API directly?

    Joel VanderWerf wrote:
    >
    > I'm stumped... how do I call instance_eval from a C extension?
    >
    > I have an object and a proc:
    >
    > VALUE obj, pr;
    >
    > and I want to eval pr with obj as self.
    >
    > Currently, I do something like this, which works, but it's inefficient:
    >
    > rb_funcall(obj, rb_intern("insteval_proc"), 1, pr);
    >
    > and I have the following defined in ruby:
    >
    > class Object
    > def insteval_proc pr
    > instance_eval &pr
    > end
    > end
    >
    > I'd rather avoid the extra method call.
    >
    > It doesn't seem like I can use rb_obj_instance_eval(), because that
    > takes string arguments, not block arguments. Of course, if you have a
    > block accompanying the method call, it will instance_eval that, but I
    > don't know how to set that up in C. That's why I do "instance_eval &pr"
    > in my little hack.
    >
    > And I can't see how to use rb_iterate(). This is what I tried:
    >
    >
    > static VALUE my_instance_eval(VALUE obj)
    > {
    > return rb_obj_instance_eval(0, 0, obj);
    > }
    >
    > static VALUE call_block(VALUE arg1, VALUE block)
    > {
    > return rb_funcall(block, ID_call, 0);
    > }
    >
    > //...
    > rb_iterate(my_instance_eval, obj, call_block, pr);
    >
    >
    > but I get "block not supplied (ArgumentError)", so I guess it's not
    > being propagted into the rb_funcall.
    Joel VanderWerf, May 2, 2004
    #2
    1. Advertising

  3. On Mon, May 03, 2004 at 03:10:24AM +0900, Joel VanderWerf wrote:
    >
    > Any ideas, anyone? Is this something you can do in ruby, but not using
    > the C API directly?
    >
    > Joel VanderWerf wrote:
    > >
    > >I'm stumped... how do I call instance_eval from a C extension?


    Take a look at
    http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/86105

    you might find it useful.

    --
    Running Debian GNU/Linux Sid (unstable)
    batsman dot geo at yahoo dot com

    Windows without the X is like making love without a partner.
    -- MaDsen Wikholm,
    Mauricio Fernández, May 2, 2004
    #3
  4. Mauricio Fernández wrote:
    > On Mon, May 03, 2004 at 03:10:24AM +0900, Joel VanderWerf wrote:
    >
    >>Any ideas, anyone? Is this something you can do in ruby, but not using
    >>the C API directly?
    >>
    >>Joel VanderWerf wrote:
    >>
    >>>I'm stumped... how do I call instance_eval from a C extension?

    >
    >
    > Take a look at
    > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/86105
    >
    > you might find it useful.


    Well, rb_iterate() is what I was trying before, but apparently it does
    not arrange for rb_block_given_p() to be true, and so
    rb_obj_instance_eval() bails out. I've adapted your example to show how
    that is the case in both your code and mine.

    The output (ruby-1.9.0 snapshot) is:

    foo2, block given = 0
    call_gsub, block given = 0
    block2, block given = 0
    Inside block, with string: h.
    block2, block given = 0
    Inside block, with string: e.
    block2, block given = 0
    Inside block, with string: l.
    block2, block given = 0
    Inside block, with string: l.
    block2, block given = 0
    Inside block, with string: l.
    "HELLo, worLd!"
    instance_eval_proc, block given = 0
    my_instance_eval, block given = 0
    example.rb:11:in `instance_eval_proc': block not supplied (ArgumentError)
    from example.rb:11


    So I'm still looking for a solution to my problem, which is: how to
    execute a Proc in the context of a given self object, from C code.

    In other words, given the following working ruby code:

    class Object
    def instance_eval_proc(pr)
    instance_eval(&pr)
    end
    end

    obj = [1,2,3]
    pr = proc { reverse }

    p obj.instance_eval_proc(pr) # ==> [3, 2, 1]

    how would you rewrite #instance_eval_proc in C?

    == extconf.rb ==

    require "mkmf"

    create_makefile("example")

    == example.rb ==

    require "example.so"

    b = "hello, world!"
    CTest.foo2(b, /[ehl]/)
    p b


    obj = [1,2,3]
    pr = proc { reverse }

    p obj.instance_eval_proc(pr)

    == example.c ==


    #include <ruby.h>
    #include <stdio.h>

    VALUE mCTest;

    static
    VALUE
    block2(VALUE str)
    {
    printf("block2, block given = %d\n", rb_block_given_p());
    Check_Type(str, T_STRING);
    printf("Inside block, with string: %s.\n", RSTRING(str)->ptr);
    return rb_funcall(str, rb_intern("upcase"), 0);
    }

    static
    VALUE
    call_gsub(VALUE args)
    {
    VALUE str, re;
    printf("call_gsub, block given = %d\n", rb_block_given_p());
    str = rb_ary_entry(args, 0);
    re = rb_ary_entry(args, 1);

    return rb_funcall(str, rb_intern("gsub!"), 1, re);
    }

    static
    VALUE
    foo2(VALUE self, VALUE str, VALUE re)
    {
    VALUE args;
    printf("foo2, block given = %d\n", rb_block_given_p());
    args = rb_ary_new();
    rb_ary_push(args, str);
    rb_ary_push(args, re);

    return rb_iterate(call_gsub, args, block2, str);
    }

    static VALUE my_instance_eval(VALUE obj)
    {
    printf("my_instance_eval, block given = %d\n", rb_block_given_p());
    return rb_obj_instance_eval(0, 0, obj);
    }

    static VALUE call_block(VALUE arg1, VALUE block)
    {
    printf("call_block, block given = %d\n", rb_block_given_p());
    return rb_funcall(block, rb_intern("call"), 0);
    }

    static VALUE instance_eval_proc(VALUE self, VALUE pr)
    {
    printf("instance_eval_proc, block given = %d\n", rb_block_given_p());
    return rb_iterate(my_instance_eval, self, call_block, pr);
    }

    void
    Init_example()
    {
    mCTest = rb_define_module("CTest");
    rb_define_singleton_method(mCTest, "foo2", foo2, 2);
    rb_define_method(rb_cObject, "instance_eval_proc", instance_eval_proc, 1);
    }
    Joel VanderWerf, May 3, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jindal, Pankaj

    ['ext.IsDOMString', 'ext.SplitQName']

    Jindal, Pankaj, Dec 22, 2004, in forum: Python
    Replies:
    0
    Views:
    308
    Jindal, Pankaj
    Dec 22, 2004
  2. Replies:
    11
    Views:
    592
  3. Replies:
    1
    Views:
    93
    Mauricio Fernández
    Jul 17, 2003
  4. Tim Bates

    instance_eval and Class Variables

    Tim Bates, Aug 6, 2003, in forum: Ruby
    Replies:
    0
    Views:
    106
    Tim Bates
    Aug 6, 2003
  5. Aron Griffis

    instance_eval and constants

    Aron Griffis, Feb 24, 2004, in forum: Ruby
    Replies:
    2
    Views:
    82
    Aron Griffis
    Feb 24, 2004
Loading...

Share This Page