EXTENDING RUBY WITH C++ - A MINI-HOW-TO Issac Trotts December 13, 2001 Attempting to create a Ruby extension using a C++ compiler is likely to give you some unhelpful compile-time and link-time errors. Here are some tips on how to get around them: COMPILE-TIME Use the following typedef to make the compiler stop complaining about the callbacks you hand to rb_define_method(): // Use this typedef to make the compiler happy when // calling rb_define_method() typedef VALUE (ruby_method)(...); ... // notice the cast to ruby_method pointer here rb_define_method(cTest, "foo", (ruby_method*) &t_foo, 0); LINK-TIME The linker will say that it can't find various functions you've defined. This is because of C++'s name-mangling, which it uses to do things like overloading functions. If you don't know what this means, don't worry. All you have to do is put extern "C" in front of your function definitions, like this: extern "C" VALUE t_foo(VALUE self) { //... } Surprisingly, 'extern "C"' means "Do not mangle the name of this function." In the long tradition of C/C++ obfuscation, 'extern "C"' does NOT mean "This function is written in the C programming language." See _More Effective C++_ (Scott Meyers) Item 34 p. 270 for details. A STEP-BY STEP EXAMPLE 1. Create a file named Test.cpp with the following contents: // BEGIN Test.cpp #include #include #include // Use this typedef to make the compiler happy when // calling rb_define_method() typedef VALUE (ruby_method)(...); extern "C" VALUE t_init(VALUE self) { VALUE arr; arr = rb_ary_new(); rb_iv_set(self, "@arr", arr); return self; } extern "C" VALUE t_add(VALUE self, VALUE obj) { VALUE arr; arr = rb_iv_get(self, "@arr"); rb_ary_push(arr, obj); return arr; } extern "C" VALUE t_foo(VALUE self) { // Make a vector of ints and print it out, just because // we can. std::vector ii; for(int i=0; i<10; i++) { ii.push_back(i); } int k=0; std::vector::iterator i2; std::cout<<"Executing foo on <"<"<