Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > instance_eval from C ext

Reply
Thread Tools

instance_eval from C ext

 
 
Joel VanderWerf
Guest
Posts: n/a
 
      04-26-2004

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?


 
Reply With Quote
 
 
 
 
Joel VanderWerf
Guest
Posts: n/a
 
      05-02-2004

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.



 
Reply With Quote
 
 
 
 
Mauricio Fernández
Guest
Posts: n/a
 
      05-02-2004
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...uby-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,


 
Reply With Quote
 
Joel VanderWerf
Guest
Posts: n/a
 
      05-02-2004
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...uby-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);
}


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Missing modules '_ssl', 'ext.IsDOMString', 'ext.SplitQName' uid09012_ti@collinsrealtime.com Python 11 10-27-2005 12:01 PM
['ext.IsDOMString', 'ext.SplitQName'] Jindal, Pankaj Python 0 12-22-2004 10:27 AM
instance_eval and constants Aron Griffis Ruby 2 02-24-2004 11:15 PM
instance_eval and Class Variables Tim Bates Ruby 0 08-06-2003 06:05 AM
instance_eval("class") error/bug??? walter@mwsewall.com Ruby 1 07-17-2003 05:29 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57