[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Converting class_for to a C extension

Daniel Berger

2/13/2007 10:27:00 PM

Hi all,

I found this snippet posted to handle doing const_get for nested
classes/modules:

def class_for(class_name)
names = class_name.split("::")
result = Object
names.each { |n|
result = result.const_get(n)
}
result
rescue NameError
nil
end

I'm trying to convert this to a C extension, but I'm having some
trouble:

static VALUE class_for(VALUE klass_name){
VALUE v_names, v_result;
ID id_split = rb_intern("split");
int i;

v_names = rb_funcall(klass_name, id_split, 1, rb_str_new2("::"));
v_result = rb_cObject;

for(i = 0; i < RARRAY(v_names)->len; i++)
v_result = rb_const_get(RBASIC(v_result)->klass, RARRAY(v_names)-
>ptr[i]);

return v_result;
}

With this code I get "uninitialized constant Class::(null)
(NameError)".

It appears to be a problem with the first argument to rb_const_get().
I'm not sure what that value should be, but I also tried
TYPE(v_result) - which caused a segfault - and just v_result - which
resulted in a similar "uninitialized constant (null) (NameError)"
error.

What am I doing wrong here?

Thanks,

Dan

PS - Yes, I realize I'm not doing error handling in the C extension -
I'm not worried about that for now.

11 Answers

Daniel Berger

2/13/2007 10:35:00 PM

0

On Feb 13, 3:26 pm, "Daniel Berger" <djber...@gmail.com> wrote:
> Hi all,
>
> I found this snippet posted to handle doing const_get for nested
> classes/modules:
>
> def class_for(class_name)
> names = class_name.split("::")
> result = Object
> names.each { |n|
> result = result.const_get(n)
> }
> result
> rescue NameError
> nil
> end
>
> I'm trying to convert this to a C extension, but I'm having some
> trouble:
>
> static VALUE class_for(VALUE klass_name){
> VALUE v_names, v_result;
> ID id_split = rb_intern("split");
> int i;
>
> v_names = rb_funcall(klass_name, id_split, 1, rb_str_new2("::"));
> v_result = rb_cObject;
>
> for(i = 0; i < RARRAY(v_names)->len; i++)
> v_result = rb_const_get(RBASIC(v_result)->klass, RARRAY(v_names)-
>
> >ptr[i]);
>
> return v_result;
>
> }
>
> With this code I get "uninitialized constant Class::(null)
> (NameError)".
>
> It appears to be a problem with the first argument to rb_const_get().
> I'm not sure what that value should be, but I also tried
> TYPE(v_result) - which caused a segfault - and just v_result - which
> resulted in a similar "uninitialized constant (null) (NameError)"
> error.
>
> What am I doing wrong here?

Naturally I saw my mistake 2 minutes later:

It should be:

for(i = 0; i < RARRAY(v_names)->len; i++){
v_result = rb_const_get(
v_result,
rb_intern(StringValuePtr(RARRAY(v_names)->ptr[i]))
);
}

Regards,

Dan

Vincent Fourmond

2/13/2007 10:39:00 PM

0

Daniel Berger wrote:
> Hi all,
>
> I found this snippet posted to handle doing const_get for nested
> classes/modules:
>
> def class_for(class_name)
> names = class_name.split("::")
> result = Object
> names.each { |n|
> result = result.const_get(n)
> }
> result
> rescue NameError
> nil
> end
>
> I'm trying to convert this to a C extension, but I'm having some
> trouble:
>
> static VALUE class_for(VALUE klass_name){
> VALUE v_names, v_result;
> ID id_split = rb_intern("split");
> int i;
>
> v_names = rb_funcall(klass_name, id_split, 1, rb_str_new2("::"));
> v_result = rb_cObject;
>
> for(i = 0; i < RARRAY(v_names)->len; i++)
> v_result = rb_const_get(RBASIC(v_result)->klass, RARRAY(v_names)-
>> ptr[i]);
>
> return v_result;
> }
>
> With this code I get "uninitialized constant Class::(null)
> (NameError)".
>
> It appears to be a problem with the first argument to rb_const_get().
> I'm not sure what that value should be, but I also tried
> TYPE(v_result) - which caused a segfault - and just v_result - which
> resulted in a similar "uninitialized constant (null) (NameError)"
> error.
>
> What am I doing wrong here?
>
> Thanks,
>
> Dan
>
> PS - Yes, I realize I'm not doing error handling in the C extension -
> I'm not worried about that for now.

You should ;-) the (null) stuff is a sign that you're using a NULL
pointer somewhere, though I can't get where. The segfault is another
indication. So one thing here is returning false or NULL...

The problem, in my opinion, is here:

RBASIC(v_result)->klass

Why do you need to use ->klass ?? All objects you're getting *are*
classes or modules already. You end up looking for constants in the
Class class, and that is not where they are defined.

Cheers,

Vince
--
Vincent Fourmond, PhD student (not for long anymore)
http://vincent.fourmon...

Lyle Johnson

2/13/2007 10:40:00 PM

0

On 2/13/07, Daniel Berger <djberg96@gmail.com> wrote:

> I found this snippet posted to handle doing const_get for nested
> classes/modules:

<snip>

I know this doesn't directly answer the question you asked, but why
not just use rb_path2class()?

Daniel Berger

2/13/2007 10:53:00 PM

0

On Feb 13, 3:40 pm, "Lyle Johnson" <lyle.john...@gmail.com> wrote:
> On 2/13/07, Daniel Berger <djber...@gmail.com> wrote:
>
> > I found this snippet posted to handle doing const_get for nested
> > classes/modules:
>
> <snip>
>
> I know this doesn't directly answer the question you asked, but why
> not just use rb_path2class()?

*SLAPS FOREHEAD*

Thanks Lyle.

Dan

Eric Hodel

2/14/2007 7:31:00 PM

0

On Feb 13, 2007, at 14:40, Lyle Johnson wrote:
> On 2/13/07, Daniel Berger <djberg96@gmail.com> wrote:
>
>> I found this snippet posted to handle doing const_get for nested
>> classes/modules:
>
> <snip>
>
> I know this doesn't directly answer the question you asked, but why
> not just use rb_path2class()?

One of these days I'm going to write a patch to expose this to Ruby :P

Lyle Johnson

2/14/2007 7:50:00 PM

0

On 2/14/07, Eric Hodel <drbrain@segment7.net> wrote:

> One of these days I'm going to write a patch to expose this to Ruby :P

Expose what to Ruby?

Daniel Berger

2/14/2007 8:00:00 PM

0

On Feb 14, 12:50 pm, "Lyle Johnson" <lyle.john...@gmail.com> wrote:
> On 2/14/07, Eric Hodel <drbr...@segment7.net> wrote:
>
> > One of these days I'm going to write a patch to expose this to Ruby :P
>
> Expose what to Ruby?

I think he just means that there's no direct equivalent in plain Ruby
(right?).

I think just patching const_get to handle "::" would suffice.

Dan

Lyle Johnson

2/14/2007 8:36:00 PM

0

On 2/14/07, Daniel Berger <djberg96@gmail.com> wrote:

> I think he just means that there's no direct equivalent in plain Ruby
> (right?).

*SLAPS FOREHEAD*

Oh, yeah. ;)

Eric Hodel

2/14/2007 8:45:00 PM

0

On Feb 14, 2007, at 12:05, Daniel Berger wrote:
> On Feb 14, 12:50 pm, "Lyle Johnson" <lyle.john...@gmail.com> wrote:
>> On 2/14/07, Eric Hodel <drbr...@segment7.net> wrote:
>>
>>> One of these days I'm going to write a patch to expose this to
>>> Ruby :P
>>
>> Expose what to Ruby?
>
> I think he just means that there's no direct equivalent in plain Ruby
> (right?).

Yup. I've reimplemented rb_path2class() numerous times in ruby, and
there's a perfectly good C method lying around that needs only a one-
line patch to be accessible.

> I think just patching const_get to handle "::" would suffice.

Possibly.

Daniel Berger

2/15/2007 3:49:00 PM

0

On Feb 14, 1:44 pm, Eric Hodel <drbr...@segment7.net> wrote:
> On Feb 14, 2007, at 12:05, Daniel Berger wrote:
>
> > On Feb 14, 12:50 pm, "Lyle Johnson" <lyle.john...@gmail.com> wrote:
> >> On 2/14/07, Eric Hodel <drbr...@segment7.net> wrote:
>
> >>> One of these days I'm going to write a patch to expose this to
> >>> Ruby :P
>
> >> Expose what to Ruby?
>
> > I think he just means that there's no direct equivalent in plain Ruby
> > (right?).
>
> Yup. I've reimplemented rb_path2class() numerous times in ruby, and
> there's a perfectly good C method lying around that needs only a one-
> line patch to be accessible.
>
> > I think just patching const_get to handle "::" would suffice.
>
> Possibly.

I tried messing with object.c yesterday, but I couldn't make it work.
Any ideas for a patch? It would be nice to get one in for 1.8.6 if
possible.

Dan