instance_eval, yield, C extensions

D

Daniel Berger

Hi all,

How do I write the code below within a C extension? I've seen a few =
threads=20
about it (including ruby-talk: 86105) but I'm just not "getting it".

# Assume Foo is a subclass of String
module Kernel
def my_meth
instance_eval{ Foo.new(yield) }
end
end

With that I can do my_meth{ "some_string" } and get back a String =
object.

I tried this:

static VALUE foo_block(VALUE self){
return rb_funcall(cFoo, rb_intern("new"), 0, rb_yield(self));
}

static VALUE kernel_foo(VALUE self){
VALUE v_proc =3D rb_proc_new(foo_block, self); /* Also tried Qnil */
return rb_funcall(rb_cObject, rb_intern("instance_eval"), 0, =
v_proc);
}

rb_define_method(rb_mKernel, "my_meth", kernel_foo, 0);

But this doesn't seem to work. When I try I do call my_meth{ =
"some_string" } I=20
get `instance_eval': block not supplied (ArgumentError)

What am I doing wrong here?

Thanks,

Dan


This communication is the property of Qwest and may contain confidential =
or
privileged information. Unauthorized use of this communication is =
strictly=20
prohibited and may be unlawful. If you have received this communication =

in error, please immediately notify the sender by reply e-mail and =
destroy=20
all copies of the communication and any attachments.
 
T

Tilman Sauerbeck

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Daniel Berger [2006-08-29 01:41]:

Hi Daniel,
I never worked with blocks in a C extension like you do, but I noticed a
general problem in your code:
static VALUE foo_block(VALUE self){
return rb_funcall(cFoo, rb_intern("new"), 0, rb_yield(self));
^
You're passing one argument (the result of rb_yield()), yet you tell
ruby to expect zero arguments. So make that 0 a 1.

static VALUE kernel_foo(VALUE self){
VALUE v_proc =3D rb_proc_new(foo_block, self); /* Also tried Qnil */
return rb_funcall(rb_cObject, rb_intern("instance_eval"), 0, v_proc);

Some problem here.

HTH,
Tilman

--=20
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

--AhhlLboLdkugWU4S
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iD8DBQFE8zw727uLisrW2w8RAvv1AJ9lIBU0nJ650Q0gDQ/fMaR5IARh9ACffAPi
kiCJInG7E+POtui2cfLT62U=
=CNuL
-----END PGP SIGNATURE-----

--AhhlLboLdkugWU4S--
 
D

Daniel Berger

Tilman said:
Daniel Berger [2006-08-29 01:41]:
=20
Hi Daniel,
I never worked with blocks in a C extension like you do, but I noticed = a
general problem in your code:
=20
static VALUE foo_block(VALUE self){
return rb_funcall(cFoo, rb_intern("new"), 0, rb_yield(self));
^
You're passing one argument (the result of rb_yield()), yet you tell
ruby to expect zero arguments. So make that 0 a 1.
=20
=20
static VALUE kernel_foo(VALUE self){
VALUE v_proc =3D rb_proc_new(foo_block, self); /* Also tried Qnil = */
return rb_funcall(rb_cObject, rb_intern("instance_eval"), 0, =
v_proc);
=20
Some problem here.
=20
HTH,
Tilman

Ok, fixing that I get "can't convert Proc into String (TypeError)".

Maybe I'm supposed to be using rb_block_proc, but I'm not entirely =
certain how=20
it works.

Thanks,

Dan


This communication is the property of Qwest and may contain confidential =
or
privileged information. Unauthorized use of this communication is =
strictly=20
prohibited and may be unlawful. If you have received this communication =

in error, please immediately notify the sender by reply e-mail and =
destroy=20
all copies of the communication and any attachments.
 
D

Daniel Berger

Daniel said:
Tilman said:
Daniel Berger [2006-08-29 01:41]:

Hi Daniel,
I never worked with blocks in a C extension like you do, but I = noticed a
general problem in your code:
static VALUE foo_block(VALUE self){
return rb_funcall(cFoo, rb_intern("new"), 0, rb_yield(self));
^
You're passing one argument (the result of rb_yield()), yet you tell
ruby to expect zero arguments. So make that 0 a 1.

static VALUE kernel_foo(VALUE self){
VALUE v_proc =3D rb_proc_new(foo_block, self); /* Also tried Qnil = */
return rb_funcall(rb_cObject, rb_intern("instance_eval"), 0, =
v_proc);

Some problem here.

HTH,
Tilman
=20
Ok, fixing that I get "can't convert Proc into String (TypeError)".
=20
Maybe I'm supposed to be using rb_block_proc, but I'm not entirely=20
certain how it works.
=20
Thanks,
=20
Dan
=20

I guess I was over thinking it. This function works by itself:

static VALUE kernel_foo(VALUE self){
return rb_funcall(cFoo, rb_intern("new"), 1, =
rb_yield(rb_block_proc()));
}

Regards,

Dan


This communication is the property of Qwest and may contain confidential =
or
privileged information. Unauthorized use of this communication is =
strictly=20
prohibited and may be unlawful. If you have received this communication =

in error, please immediately notify the sender by reply e-mail and =
destroy=20
all copies of the communication and any attachments.
 
E

Eero Saynatkari

Daniel said:
Ok, fixing that I get "can't convert Proc into String (TypeError)".

Right now that code is equivalent to

obj.instance_eval block

Where it should be

obj.instance_eval &block
obj.instance_eval {some_code}
obj.instance_eval 'some_code'
 
T

ts

D> static VALUE kernel_foo(VALUE self){
D> return rb_funcall(cFoo, rb_intern("new"), 1, rb_yield(rb_block_proc()));
^^^^^^^^^^^^^^^

You are giving the proc to the block, you have writing something like thid

def xxx(&block)
Foo.new(yield(block))
end
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,169
Latest member
ArturoOlne
Top