All of this talk in regards to RubyInline made me start thinking about
combining C (or C++) and Ruby. I have been working with Ruby for some
time now and it is amazing how much fun it is to program with Ruby (as
compared to my years of toil with C and C++ and forays into Perl). I
would like to use Ruby in all of my programming, but unfortunately, my
domain at work is image processing (routinely working with 3D data of
hundreds of mega-voxels) and performance is key.
To use Ruby for this domain, the only real option, of course, is to
mix Ruby and C (or C++), perhaps via SWIG or things like RubyInline or
cgenerator. And this would probably be a reasonable way to approach
it. But, what if we took things further and integrated the use
of C or C++ into Ruby itself. If we fully integrated C and C++ into
Ruby there would be no problem domain which it could not cover.
Here is what I had in mind:
module ImageProcessing
class Image
# lots of defs here
end
# Add v to each image pixel, assumes images are 8 bits/pixel
cdef void add(VALUE image, unsigned char v)
unsigned char *pix = rb_funcall(image, rb_intern("pixel_ptr"), 0);
long n_pixels = rb_funcall(image, rb_intern("n_pixels"), 0);
for(long i=0; i<n_pixels; i++)
*pix++ = *pix + v
end
# Increment all pixels
def inc(image)
add(image, 1)
end
end
But we could take this further. The code above assumes that the
Image class defines images where each pixel is a byte. What if
we want to handle images with floats (or longs or …) as pixels?
And maybe we want to define some objects in C++.
We could introduce some kind of dynamic templating (reminding me
a little of the multi-methods discussion):
class Object
def c_type
"VALUE"
end
end
class Float
def c_type
"float"
end
end
module ImageProcessing
c_class ByteImage # a c++ class
unsigned char *pixel_ptr() { … }
char *c_type() { return “ByteImage *” };
char *pixel_type() { return “unsigned char” };
end
c_class FloatImage
float *pixel_ptr() { ... }
char *c_type() { return "FloatImage *" };
char *pixel_type() { return "float" };
end
# Add v to each image pixel.
# Ruby will auto-generate C++ code for this based on the types it
# sees on input (and compile and cache the result).
cdef void add(image, #{image.pixel_type} v)
#{image.pixel_type} *pix = image->pixel_ptr();
long n_pixels = image->n_pixels();
for(long i=0; i<n_pixels; i++)
*pix++ = *pix + v
end
# Increment all pixels
def inc(image)
add(image, 1)
end
end
I know I am glossing over many things, but I hope you get the idea.
By allowing one to use Ruby as sort of a templating language for
its C or C++ extensions you could do some really amazing things.
And making inline C or C++ a first class part of the Ruby language
you would erase the only negative I see in the language for some
domains–performance. Thoughts?
Derek Ney
derek @ hipgraphics . com