[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Alias singleton method from C

Ross Bamford

10/30/2006 1:56:00 PM

Hi,

I think I must have missed something obvious, but I can't see how to
alias a singleton method from a C extension. I think I can grab the
singleton class, then pass that to rb_alias, but is that the right /
best way to do it? Is there a define_singleton_alias somewhere that I've
failed to spot?

Any help would be much appreciated.

Thanks,
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk


6 Answers

Daniel Berger

10/30/2006 4:32:00 PM

0

Ross Bamford wrote:
> Hi,
>
> I think I must have missed something obvious, but I can't see how to
> alias a singleton method from a C extension. I think I can grab the
> singleton class, then pass that to rb_alias, but is that the right /
> best way to do it? Is there a define_singleton_alias somewhere that I've
> failed to spot?
>
> Any help would be much appreciated.

Good question. I'm not sure why this code fails:

#include <ruby.h>

static VALUE foo_bar(){
return rb_str_new2("hello");
}

void Init_foo(){
VALUE cFoo, singleton;

cFoo = rb_define_class("Foo", rb_cObject);

rb_define_singleton_method(cFoo, "bar", foo_bar, 0);

singleton = rb_const_get(rb_cObject, rb_intern("Foo"));
rb_define_alias(singleton, "baz", "bar");
}

When I compile and run that it fails with "undefined method `bar' for
class `Foo'" even though it clearly is defined. I can see in class.c
that rb_define_alias is just calling rb_alias from eval.c. It looks
like rb_alias handles singletons differently, but why it's not working
in the example I provided I'm not sure.

Hopefully Matz or Guy will pipe up.

Regards,

Dan

Tim Pease

10/30/2006 4:52:00 PM

0

On 10/30/06, Daniel Berger <djberg96@gmail.com> wrote:
>
> Good question. I'm not sure why this code fails:
>
> #include <ruby.h>
>
> static VALUE foo_bar(){
> return rb_str_new2("hello");
> }
>
> void Init_foo(){
> VALUE cFoo, singleton;
>
> cFoo = rb_define_class("Foo", rb_cObject);
>
> rb_define_singleton_method(cFoo, "bar", foo_bar, 0);
>
> singleton = rb_const_get(rb_cObject, rb_intern("Foo"));
> rb_define_alias(singleton, "baz", "bar");
> }
>
> When I compile and run that it fails with "undefined method `bar' for
> class `Foo'" even though it clearly is defined. I can see in class.c
> that rb_define_alias is just calling rb_alias from eval.c. It looks
> like rb_alias handles singletons differently, but why it's not working
> in the example I provided I'm not sure.
>

rb_define_alias only works for instance methods.
rb_define_singleton_method is the same as saying

class Foo
class << self
def bar( ) "hello" end
end
alias :baz :bar
end

That is going to fail because you have not defined a method "bar" in
the Foo class. It is defined in the Foo singleton class.

Does that make sense or help at all? I've got to run to a meeting, so
I don't have time to work out the correct way of doing it. That's
left as an exercise for the reader ;)

Blessings,
TwP

Daniel Berger

10/30/2006 5:08:00 PM

0

Tim Pease wrote:
> On 10/30/06, Daniel Berger <djberg96@gmail.com> wrote:
> >
> > Good question. I'm not sure why this code fails:
> >
> > #include <ruby.h>
> >
> > static VALUE foo_bar(){
> > return rb_str_new2("hello");
> > }
> >
> > void Init_foo(){
> > VALUE cFoo, singleton;
> >
> > cFoo = rb_define_class("Foo", rb_cObject);
> >
> > rb_define_singleton_method(cFoo, "bar", foo_bar, 0);
> >
> > singleton = rb_const_get(rb_cObject, rb_intern("Foo"));
> > rb_define_alias(singleton, "baz", "bar");
> > }
> >
> > When I compile and run that it fails with "undefined method `bar' for
> > class `Foo'" even though it clearly is defined. I can see in class.c
> > that rb_define_alias is just calling rb_alias from eval.c. It looks
> > like rb_alias handles singletons differently, but why it's not working
> > in the example I provided I'm not sure.
> >
>
> rb_define_alias only works for instance methods.

It should work for either singletons or instance methods. If it
didn't, then this code wouldn't work:

class Foo
class << self
def bar
"hello"
end
alias baz bar
end
end

p Foo.bar => "hello"
p Foo.baz => "hello"

The C example I pasted is meant to do what I've done there.

Internally rb_define_alias calls rb_alias (in eval.c) which checks to
see if klass is a singleton or not. So, in theory, I should be able to
do:

rb_define_alias(singleton, baz, bar);

But obviously I'm doing something wrong - I'm just not sure what.

Regards,

Dan

PS - A rb_define_singleton_alias() would be a handy function. :)

Ross Bamford

10/30/2006 6:10:00 PM

0

On Tue, 2006-10-31 at 02:10 +0900, Daniel Berger wrote:
> Tim Pease wrote:
> > On 10/30/06, Daniel Berger <djberg96@gmail.com> wrote:
> > >
> > > Good question. I'm not sure why this code fails:
> > >
> > > #include <ruby.h>
> > >
> > > static VALUE foo_bar(){
> > > return rb_str_new2("hello");
> > > }
> > >
> > > void Init_foo(){
> > > VALUE cFoo, singleton;
> > >
> > > cFoo = rb_define_class("Foo", rb_cObject);
> > >
> > > rb_define_singleton_method(cFoo, "bar", foo_bar, 0);
> > >
> > > singleton = rb_const_get(rb_cObject, rb_intern("Foo"));
> > > rb_define_alias(singleton, "baz", "bar");
> > > }
> > >
> > > When I compile and run that it fails with "undefined method `bar' for
> > > class `Foo'" even though it clearly is defined. I can see in class.c
> > > that rb_define_alias is just calling rb_alias from eval.c. It looks
> > > like rb_alias handles singletons differently, but why it's not working
> > > in the example I provided I'm not sure.
> > >
> >
> > rb_define_alias only works for instance methods.
>
> It should work for either singletons or instance methods. If it
> didn't, then this code wouldn't work:
>
> class Foo
> class << self
> def bar
> "hello"
> end
> alias baz bar
> end
> end
>
> p Foo.bar => "hello"
> p Foo.baz => "hello"
>
> The C example I pasted is meant to do what I've done there.
>
> Internally rb_define_alias calls rb_alias (in eval.c) which checks to
> see if klass is a singleton or not. So, in theory, I should be able to
> do:
>
> rb_define_alias(singleton, baz, bar);
>
> But obviously I'm doing something wrong - I'm just not sure what.

This is similar to what I was going to do - you just need to get the
singleton class from the class. I _think_ in your example, cFoo ==
singleton. Something like this works:

/* define singleton methods as normal */

VALUE singleton = rb_singleton_class(cXMLNode);
rb_define_alias(singleton, "new_element", "new");

I guess that would work with rb_alias too, but I thought there had to be
a wrapper for this somewhere that I'd missed.

> PS - A rb_define_singleton_alias() would be a handy function. :)
>

Agreed. Assuming it's not already lurking somewhere, that is. :)

Cheers,
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk


Tim Pease

10/30/2006 6:10:00 PM

0

On 10/30/06, Daniel Berger <djberg96@gmail.com> wrote:
> Tim Pease wrote:
> > On 10/30/06, Daniel Berger <djberg96@gmail.com> wrote:
> > >
> > > void Init_foo(){
> > > VALUE cFoo, singleton;
> > >
> > > cFoo = rb_define_class("Foo", rb_cObject);
> > >
> > > rb_define_singleton_method(cFoo, "bar", foo_bar, 0);
> > >
> > > singleton = rb_const_get(rb_cObject, rb_intern("Foo"));
> > > rb_define_alias(singleton, "baz", "bar");
> > > }
> > >

Your line of code above that grabs the singleton class is incorrect.

singleton = rb_const_get( rb_cObject, rb_intern("Foo"));

This will just return the class object for your "Foo" class. In this
case singleton is equivalent to cFoo. Try this out in your code ...

singleton == cFoo

That should equate to true. Here is the correct way to grab the
singleton class from C code ...

> cat foo.c
#include <ruby.h>

static VALUE
foo_bar( VALUE self ) {
return rb_str_new2( "hello" );
}


void
Init_foo( ) {
VALUE cFoo, singleton;

cFoo = rb_define_class("Foo", rb_cObject);

rb_define_singleton_method(cFoo, "bar", foo_bar, 0);

singleton = rb_singleton_class(cFoo);
rb_define_alias(singleton, "baz", "bar");
}

Now you can do this ...

Foo.bar #=> "hello"
Foo.baz #=> "hello"


The magic syntax is the line ...

singleton = rb_singleton_class(cFoo);

That gives me Foo's singleton.

Blessings,
TwP

Daniel Berger

10/30/2006 6:32:00 PM

0

Ross Bamford wrote:

<snip>

> /* define singleton methods as normal */
>
> VALUE singleton = rb_singleton_class(cXMLNode);
> rb_define_alias(singleton, "new_element", "new");

Bingo. That's what you want. I was just getting the singleton wrong.

- Dan