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.
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
···
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?
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.fourmond.neuf.fr/
<snip>
I know this doesn't directly answer the question you asked, but why
not just use rb_path2class()?
···
On 2/13/07, Daniel Berger <djberg96@gmail.com> wrote:
I found this snippet posted to handle doing const_get for nested
classes/modules:
One of these days I'm going to write a patch to expose this to Ruby 
···
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()?
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
···
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 
Expose what to Ruby?
One of these days I'm going to write a patch to expose this to Ruby 
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.
···
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:
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
···
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 
>> 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.
Oh, I was mistaken, its VALUE rb_path2class(const char *) not VALUE rb_path2class(VALUE), so a wrapper function needs to be written (so more than one line). I don't know if Object::path2class is a good name, since the C implementation can only have Object as its root.
I got this far:
Index: intern.h
···
On Feb 15, 2007, at 07:50, Daniel Berger wrote:
On Feb 14, 1:44 pm, Eric Hodel <drbr...@segment7.net> wrote:
On Feb 14, 2007, at 12:05, Daniel Berger wrote:
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 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.
===================================================================
--- intern.h (revision 11758)
+++ intern.h (working copy)
@@ -453,6 +453,7 @@ VALUE rb_mod_name _((VALUE));
VALUE rb_class_path _((VALUE));
void rb_set_class_path _((VALUE, VALUE, const char*));
VALUE rb_path2class _((const char*));
+VALUE rb_obj_path2class _((VALUE));
void rb_name_class _((VALUE, ID));
VALUE rb_class_name _((VALUE));
void rb_autoload _((VALUE, ID, const char*));
Index: variable.c
--- variable.c (revision 11758)
+++ variable.c (working copy)
@@ -274,6 +274,13 @@ rb_path2class(path)
return c;
}
+VALUE
+rb_obj_path2class(path)
+ VALUE path;
+{
+ return rb_path2class(StringValueCStr(path));
+}
+
void
rb_name_class(klass, id)
VALUE klass;
Index: object.c
--- object.c (revision 11758)
+++ object.c (working copy)
@@ -2646,7 +2646,7 @@ Init_Object()
rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);
-
+ rb_define_singleton_method(rb_cObject, "path2class", rb_obj_path2class, 1);
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
$ ./ruby186 -e 'p Object.path2class("Struct")'
-e:1:in `path2class': can't convert Class into String (TypeError)
from -e:1