If I have Foo::Bar written in Ruby, and I want to add a method to Bar as a C extension. Right now when I create Foo::Bar in C like this:
static VALUE Foo;
static VALUE Bar;
static VALUE
print_string(VALUE self, VALUE string) {
printf("%s", StringValuePtr(string));
return Qnil;
}
void Init_foo() {
Foo = rb_define_module("Foo");
Bar = rb_define_class_under(Foo, "Bar", rb_cObject);
rb_define_method(Bar, "print_string", print_string, 1);
}
But the problem is:
ruby-1.9.2-p180 :001 > require 'ext/foo' #=> ["Foo"]
ruby-1.9.2-p180 :002 > f = Foo::Bar.new #=> #<Foo::Bar:0x000001046bce48>
ruby-1.9.2-p180 :003 > f.original_ruby_method
NoMethodError: undefined method `original_ruby_method' for #<Foo::Bar:0x000001046bce48>
So I am essentially overwriting the original Foo::Bar. How do I extend it and not overwrite it?
An alternative to your solution, where you require your Ruby code from your C extension, would be to require the extension from the Ruby code.
Add require 'foo.so'
or require 'ext/foo.so'
(depending on where your compiled library ends up) to lib/foo.rb
, then in the client code just call require 'foo'
as normal (assuming lib
is on your load path).
I think doing it this way round is clearer and more common.
Note that you can use the .so
suffix even if your platform produces something else, i.e. it'll still work on a mac when the actual file is a .bundle
.