[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Extension question

Joe Van Dyk

4/4/2005 2:20:00 PM

Hi,

I'm generating a fairly large image file (can be 10000x10000) pixels
by reading some binary data and setting each pixel. As you can
imagine, pure Ruby is REALLY slow, I think because of the loops. I've
written the program in C and it's literally hundreds to thousands of
times faster (depending on image size).

So, I'd like to write my first C extension. I'm using the GD library
for image manipulation.

Are there any general rules of thumb that you use when writing extensions?

My first problem was trying to figure out what should remain Ruby code
and what should be moved out to C. For example, if I opened the file
that contained binary data in Ruby, how could I "get" to that data
using a FILE pointer in C? Or should I just pass the filename to the
C extension?

Also, I couldn't really figure out how to only have one function in C,
the documentation seemed to say that I needed to have a class?

Thanks,
Joe


24 Answers

Tom Copeland

4/4/2005 2:46:00 PM

0

On Mon, 2005-04-04 at 23:19 +0900, Joe Van Dyk wrote:
> Hi,
>
> I'm generating a fairly large image file (can be 10000x10000) pixels
> by reading some binary data and setting each pixel. As you can
> imagine, pure Ruby is REALLY slow, I think because of the loops. I've
> written the program in C and it's literally hundreds to thousands of
> times faster (depending on image size).
>
> So, I'd like to write my first C extension. I'm using the GD library
> for image manipulation.

You might be interested in this:

http://raa.ruby-lang.org/list.rhtml?na...

>From the example scripts:

require "GD"
im = GD::Image.new(100,100)
red = im.colorAllocate(255,0,0)
im.rectangle(0,0,99,99,red)
im.png STDOUT

Yours,

tom




Tom Copeland

4/4/2005 3:01:00 PM

0

On Mon, 2005-04-04 at 23:19 +0900, Joe Van Dyk wrote:
> Also, I couldn't really figure out how to only have one function in C,
> the documentation seemed to say that I needed to have a class?

You can attach the function to Object:

===============================
$ cat example.c
#include <stdio.h>
#include "ruby.h"
static VALUE test(VALUE self) {
printf("HI!\n");
return Qnil;
}
void Init_example() {
rb_define_method(rb_cObject, "test", test, 0);
}
$ cat extconf.rb
require 'mkmf'
create_makefile("example")
$ ruby extconf.rb && make
[... some gcc output ...]
$ irb irb
irb(main):001:0> require 'example'
=> true
irb(main):002:0> test
HI!
=> nil
irb(main):003:0>
===============================

Yours,

Tom




Tom Copeland

4/4/2005 3:05:00 PM

0

On Mon, 2005-04-04 at 23:19 +0900, Joe Van Dyk wrote:
> My first problem was trying to figure out what should remain Ruby code
> and what should be moved out to C. For example, if I opened the file
> that contained binary data in Ruby, how could I "get" to that data
> using a FILE pointer in C? Or should I just pass the filename to the
> C extension?

I wonder about this as well. So far I've been sort of passing data
objects back and forth between C and Ruby, the same way that I would if
I were doing an out-of-process method call. But I think that's mostly
just because I'm an extensions new bee....

Yours,

Tom




Joe Van Dyk

4/4/2005 3:17:00 PM

0

On Apr 4, 2005 7:46 AM, Tom Copeland <tom@infoether.com> wrote:
> On Mon, 2005-04-04 at 23:19 +0900, Joe Van Dyk wrote:
> > Hi,
> >
> > I'm generating a fairly large image file (can be 10000x10000) pixels
> > by reading some binary data and setting each pixel. As you can
> > imagine, pure Ruby is REALLY slow, I think because of the loops. I've
> > written the program in C and it's literally hundreds to thousands of
> > times faster (depending on image size).
> >
> > So, I'd like to write my first C extension. I'm using the GD library
> > for image manipulation.
>
> You might be interested in this:
>
> http://raa.ruby-lang.org/list.rhtml?na...
>
> >From the example scripts:
>
> require "GD"
> im = GD::Image.new(100,100)
> red = im.colorAllocate(255,0,0)
> im.rectangle(0,0,99,99,red)
> im.png STDOUT
>
> Yours,

Hi,

I was using Ruby-GD before. The slowness is not the library, but the
looping 10 million times. I have to set each pixel, so I can't use
the rectangle function.


Robert Klemme

4/4/2005 3:23:00 PM

0


"Tom Copeland" <tom@infoether.com> schrieb im Newsbeitrag
news:1112626649.3468.41.camel@hal...
> On Mon, 2005-04-04 at 23:19 +0900, Joe Van Dyk wrote:
> > Also, I couldn't really figure out how to only have one function in C,
> > the documentation seemed to say that I needed to have a class?
>
> You can attach the function to Object:

IMHO the appropriate place would be a private singleton method of Kernel
wouldn't it? At least all other "functions" (gsub, gsub! etc.) are placed
there...

Kind regards

robert

Charles Mills

4/4/2005 3:29:00 PM

0


> Are there any general rules of thumb that you use when writing
extensions?

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-...

You shouldn't be able to cause your extension to seg fault from Ruby.
That may sound like a joke, but I just mean using StringValue,
NUM2LONG, etc before you starting using Ruby objects in C.

>
> My first problem was trying to figure out what should remain Ruby
code
> and what should be moved out to C. For example, if I opened the file
> that contained binary data in Ruby, how could I "get" to that data
> using a FILE pointer in C? Or should I just pass the filename to the
> C extension?
>
You can do either. IMO it depends on the layout of the file. If your
reading line by line you can do this easily using the rb_io_* functions
found in intern.h. If your going to be moving the file position
around, using fgetc/ungetc, or reading into C structs it may be easier
to use the stdio functions directly.

-Charlie

Tom Copeland

4/4/2005 3:51:00 PM

0

On Tue, 2005-04-05 at 00:17 +0900, Joe Van Dyk wrote:
> I was using Ruby-GD before.

Ah, OK, so you were already familiar with that one, sorry.

Yours,

Tom




Tom Copeland

4/4/2005 3:52:00 PM

0

On Tue, 2005-04-05 at 00:24 +0900, Robert Klemme wrote:
> > You can attach the function to Object:
>
> IMHO the appropriate place would be a private singleton method of Kernel
> wouldn't it? At least all other "functions" (gsub, gsub! etc.) are placed
> there...

Right you are, that's much better...

Yours,

Tom




Tim Hunter

4/4/2005 4:47:00 PM

0

Joe Van Dyk wrote:
> Hi,
>
> I'm generating a fairly large image file (can be 10000x10000) pixels
> by reading some binary data and setting each pixel. As you can
> imagine, pure Ruby is REALLY slow, I think because of the loops. I've
> written the program in C and it's literally hundreds to thousands of
> times faster (depending on image size).

Have you tried RMagick? http://rmagick.rub....

The constitute method may be useful:
http://www.simplesystems.org/RMagick/doc/image1.html#...

That method requires you to have all the pixel data in memory at once,
though, which could be a problem unless you have a LOT of RAM.

You could use import_pixels to set just a subset of pixels at a time:
http://www.simplesystems.org/RMagick/doc/image2.html#imp...

That would minimize the memory requirements.

In both cases you'd have to convert your binary data to a Ruby numeric
type. Don't know whether that would be too slow or not.

Charles Mills

4/4/2005 5:25:00 PM

0


Tom Copeland wrote:
> On Tue, 2005-04-05 at 00:24 +0900, Robert Klemme wrote:
> > > You can attach the function to Object:
> >
> > IMHO the appropriate place would be a private singleton method of
Kernel
> > wouldn't it? At least all other "functions" (gsub, gsub! etc.) are
placed
> > there...
>
> Right you are, that's much better...
>
> Yours,
>
> Tom

you can also put them in a module quite easily:

void
Init_myext(void)
{
VALUE m = rb_define_module("M");
rb_define_singleton_method(m, "test", some_func, -1);
}

now you have M.test()

-Charlie