class A::B verses module A ; class B

J

Jeff Mitchell

module A
FOO = 99
end

module A
class B
puts "FOO is #{FOO}" # => "FOO is 99"
end
end

class A::B
puts "FOO is #{FOO}" # error
end

Comments? I assumed the two forms were equivalent until I ran into
this. Is there a reason they should be different? I prefer the
second form, if only to save some indentation space.
 
A

Austin McDonald

Hi, I'm attempting to transfer some intensive functions from Ruby to C,
but I'd like to put as little of my code in C as possible. So, I'm
trying to access a class defined entirely in Ruby from my C code.
Specifically, I need to create an instance of this class (called
Population) and access some of its methods. A few questions about this:

1) Do the functions I need to use have to be implemented in C as well,
or can I access their "ruby version" using some C functions? What C
functions do I need to use to do this?

2) Is there a decent C API document anywhere? I've read through
"Programming Ruby," and its chapter on extending in C seems adequate for
getting started, but leaves out a lot and simply refers one to the
horribly unreadable header files, which give little to no indication as
to what each function does.

And, on a related note:

3) What kind of IDE have you found to be good for co-development of
Ruby/C code? I'm currently working with Dev-C++ (www.bloodshed.net),
and with some tweaking it seems usable. Is there anything better?

Thanks very much,
Austin McDonald
 
D

daz

Austin said:
Hi, I'm attempting to transfer some intensive functions from Ruby to C,
but I'd like to put as little of my code in C as possible. So, I'm
trying to access a class defined entirely in Ruby from my C code.
Specifically, I need to create an instance of this class (called
Population) and access some of its methods. A few questions about this:

1) Do the functions I need to use have to be implemented in C as well,
or can I access their "ruby version" using some C functions? What C
functions do I need to use to do this?

Seemless beauty is what you'll find :)
Define an empty class (if its name is known) in the Init_foo part of
your extension - look at any other extension to get clues (rb_define_class).

Reopen your class (looks the same as a class definition) and define
your methods inside it (all in Ruby):

class Foo
def a
# whatever
end

def b
end
end

Call them from C using the rb_funcall family.
2) Is there a decent C API document anywhere? I've read through
"Programming Ruby," and its chapter on extending in C seems adequate for
getting started, but leaves out a lot and simply refers one to the
horribly unreadable header files, which give little to no indication as
to what each function does.

Co-author of "Programming Ruby," (and so much more relating to Ruby)
Dave Thomas has documented the API in the .c files if you grab a
reasonably up-to-date copy of the source distribution.
And, on a related note:

3) What kind of IDE have you found to be good for co-development of
Ruby/C code? I'm currently working with Dev-C++ (www.bloodshed.net),
and with some tweaking it seems usable. Is there anything better?

Ooooh, that was sneaky; you just want to ensure that this thread
grows to 35+ replies, but the downside is that no-one gets round
to answering your main questions.
My answer is: You /know/ there are better IDE's that Dev-C++, even free
ones, but there isn't just one for Ruby and I use a low-priced
shareware one on Windows which is an anagram of UtralEdti and has
ctag support, macros, blah ... Everyone else uses their favourite
and they're all better than mine, OK.
Thanks very much,

Thank you for choosing Ruby ;-)


daz
 
D

daz

I said:
Seemless beauty is what you'll find :)

<gasps>

Seamless, not seemless (which has a completely unintended meaning)

I can spell correctly only /after/ posting (and sleep).


daz
 
A

Austin McDonald

Thanks for the excellent reply - I was thinking I'd have to do something
along those lines. I'm pleased to know that it works, though, and that
it's fairly intuitive. And thanks for the tip on the source code; I'm
sure it'll be useful in the future. (I'm sure these jokes have all been
made by this point, but Dave Thomas? Isn't he the founder of Wendy's?)

And it wasn't my intention to start a lengthy thread about IDEs; I was
just hoping for something that could do both Ruby and C with equal
skill, or even in the same IDE, (or really, anything decent for Ruby at
all :) ) Oh well, it'll give the night-owls like myself something to
post about when they can't sleep.

As I guess is apparent from my questions, I'm pretty new to Ruby, and
I've been very impressed with how easy it is to do things in this
language. My only complaint (thus far) is the insane slowness; hence,
my desire to write C extensions. Hopefully that route will pan out for me.

Thanks again,
Austin McDonald
 
A

Austin McDonald

Yeah, caught that - hilarious that that small of a typo makes a decent
sentence, yet such a totally different meaning. I love English :).

Austin
 
D

daz

Austin said:
I'm sure these jokes have all been made by this point, but Dave Thomas?
Isn't he the founder of Wendy's?

I think he's everything except that :)
I have a feeling he's away atm, but if he was near his laptop
he wouldn't be afraid to use it.
(Haven't heard that in the UK, anyway)
And it wasn't my intention to start a lengthy thread about IDEs; I was
just hoping for something that could do both Ruby and C with equal
skill, or even in the same IDE, (or really, anything decent for Ruby at
all :) )

Ah, both. Can't spell or read now.
To be honest, I use Ruby Development Environment (RDE - Windows only)
for Ruby and UE for C.
As I guess is apparent from my questions, I'm pretty new to Ruby, and
I've been very impressed with how easy it is to do things in this
language. My only complaint (thus far) is the insane slowness ...

Nooo, you've done it again, that'll be high 70's in replies.

Have to leave you to the wolves: I'm the only nice person here --
(apart from the rest).


cheers,

daz
 
K

Kent Dahl

Jeff said:
module A
FOO = 99
end

module A
class B
puts "FOO is #{FOO}" # => "FOO is 99"
end
end

class A::B
puts "FOO is #{FOO}" # error
end

Comments? I assumed the two forms were equivalent until I ran into
this. Is there a reason they should be different? I prefer the
second form, if only to save some indentation space.

I'm on the "hope it's a feature" side on this one. It means you have to
explicitly open namespaces you want to use, and the A::B shortcut
notation only opens the last namespace.

Some of this has already been discussed in the thread
"Nested class/module namespace", see [rubytalk:78843] for Matz' answer.

http://rubytalk.com/78843
 
G

Gavin Sinclair

I'm on the "hope it's a feature" side on this one. It means you have to
explicitly open namespaces you want to use, and the A::B shortcut
notation only opens the last namespace.

I dislike the behaviour displayed above. But your explanation for it
is quite reasonable.
Some of this has already been discussed in the thread
"Nested class/module namespace", see [rubytalk:78843] for Matz' answer.

I think in Ruby 2.0 there will be a change in the way constants are
resolved (see Matz's slides, wherever they lay). That would most
likely mean that how you arrived at a particular namespace is
irrelevant.

Gavin
 
J

Joel VanderWerf

daz said:
Seemless beauty is what you'll find :)
Define an empty class (if its name is known) in the Init_foo part of
your extension - look at any other extension to get clues (rb_define_class).

Reopen your class (looks the same as a class definition) and define
your methods inside it (all in Ruby):

class Foo
def a
# whatever
end

def b
end
end

Call them from C using the rb_funcall family.

This isn't going to help much, if at all, with the speed of these calls,
since it still goes thru the usual method lookup. Maybe that's ok, if
the bottleneck is not these calls, but the code around them.

If you want to avoid the overhead of method calls, you have to trade
away the flexibility of method lookup. The ruby source has many nice
models for doing this. For instance, the method Array#push (in array.c)
is callable from C code in (at least) two ways:

ID id_push = rb_intern("push");
rb_funcall(ary, id_push, 1, item);

and

rb_ary_push(ary, item);

The former goes thru the usual lookup. The latter skips directly to the
C function which implements push.

If you want objects of your class to be efficiently accessible from C,
you may also want to use the DATA type, so that you don't have to look
up instance variables, but can directly access the underlying struct.
That's no longera class defined entirely in ruby, though.
 
D

daz

Joel said:
This isn't going to help much, if at all, with the speed of these calls,
since it still goes thru the usual method lookup. Maybe that's ok, if
the bottleneck is not these calls, but the code around them.

I should have said that. To gain any speed benefit from the extension,
you'd have to cut the intensive bits out of Ruby code and write them in C.

You might use rb_define_method() / rb_define_singleton_method() when
building your class instead of creating an empty class.

More help on the Ruby API is in README.EXT in the source distro.

-----

The profile library (described in Programming Ruby under "Standard Libraries")
can help you to track down where the bottlenecks are in your Ruby script and
you should be able to find ways of reducing the need for C.

require 'profile' # at the top of your script

With experience, you'll find ways to avoid making Ruby do unnecessary,
time-consuming work like object duplication.


daz
 
A

Austin McDonald

Thanks for all the help with my last set of questions.

I'm writing a function in my C extension where I copy a variable from my
object structure to a temporary location. Then, I put a new instance in
the new location. However, Ruby keeps garbage collecting the new
variable. I fixed this error by disabling GC for awhile, then
re-enabling it when I'm done. Is there a nicer way to do that?

Code snippet:

static VALUE
pop_reproduce(VALUE self, VALUE payoffs) {
rb_gc_disable();
Population* p;
Data_Get_Struct(self, Population, p);

VALUE oldArray = p->popArray;
p->popArray = rb_ary_new2(p->size);

/*...do some stuff...*/

rb_gc_enable();
return self;
}

In this code snippet, p->popArray is the one getting GC'd. My mark
function only does this:

void pop_mark(VALUE self) {
Population* p;
Data_Get_Struct(self, Population, p);
rb_gc_mark(p->popArray);
}

It's possible that popArray isn't what is getting GC'ed; did I write the
mark function wrong? Here's where I register the mark function:

VALUE
pop_new(VALUE class, VALUE size, VALUE tagsize, VALUE strategysize) {
Population* p = ALLOC(Population);
/* do some stuff to the struct*/
VALUE obj = Data_Wrap_Struct(class, pop_mark, free, p);
VALUE argv[3];
argv[0]=size;
argv[1]=tagsize;
argv[2]=strategysize;
rb_obj_call_init(obj, 3, argv);
return obj;
}

Anyway, I realize that's a lot of code to paste... I'm just wondering if
there's any way to fix this short of actually disabling the GC.

Thanks,
Austin McDonald
 
T

ts

A> In this code snippet, p->popArray is the one getting GC'd. My mark
A> function only does this:

Your mark function is wrong, you must write it

A> void pop_mark(VALUE self) {
A> Population* p;
A> Data_Get_Struct(self, Population, p);
A> rb_gc_mark(p->popArray);
A> }

void pop_mark(Population *)
{
rb_gc_mark(p->popArray);
}


A> VALUE
A> pop_new(VALUE class, VALUE size, VALUE tagsize, VALUE strategysize) {

it's best if you use the scheme allocate/initialize rather than new

A> Population* p = ALLOC(Population);
A> /* do some stuff to the struct*/
A> VALUE obj = Data_Wrap_Struct(class, pop_mark, free, p);

best to use Data_Make_Struct

obj = Data_Make_Struct(class, Population, pop_mark, free, p);

the advantage is that p will be filled with zero, it's important for the
GC (try to avoid the variable name `class')


A> VALUE argv[3];



Guy Decoux
 
A

Austin McDonald

Thanks; sorry about the neophyte question.

Austin
A> In this code snippet, p->popArray is the one getting GC'd. My mark
A> function only does this:

Your mark function is wrong, you must write it

A> void pop_mark(VALUE self) {
A> Population* p;
A> Data_Get_Struct(self, Population, p);
A> rb_gc_mark(p->popArray);
A> }

void pop_mark(Population *)
{
rb_gc_mark(p->popArray);
}


A> VALUE
A> pop_new(VALUE class, VALUE size, VALUE tagsize, VALUE strategysize) {

it's best if you use the scheme allocate/initialize rather than new

A> Population* p = ALLOC(Population);
A> /* do some stuff to the struct*/
A> VALUE obj = Data_Wrap_Struct(class, pop_mark, free, p);

best to use Data_Make_Struct

obj = Data_Make_Struct(class, Population, pop_mark, free, p);

the advantage is that p will be filled with zero, it's important for the
GC (try to avoid the variable name `class')


A> VALUE argv[3];



Guy Decoux
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top