daniel åkerud
1/28/2008 7:51:00 AM
[Note: parts of this message were removed to make it a legal post.]
Here are some hurdles that I overcame when coding a Ruby Extension in C++ on
Win32. Feel free to add to this or to comment. I hope it will help someone
someday. (If you ask WHY?, my answer is: I'm very comfy with STL).
1. For Win32, mkmf generates makefiles for Visual Studio. In other words,
"make" won't work for you on Win32, you have to type "nmake". I used VC6.
And to use C++, the files you compile must be named ".cpp", not ".c" so that
they are compiled as c++ files instead of c files. Perhaps .cc extension
works, I didn't try.
2. Your static functions cannot be passed down to rb_define_method,
rb_define_global_function etc. The solution is not obvious. My first
thought, extern "C", __cdecl/__stdcall etc, does not do _anything_ to solve
it. You have to do the following (found somewhere on net):
// first a typedef
typedef VALUE (*HOOK)(...);
// then do a reinterpret_cast:
rb_define_method(rb_cYadaYada, "initialize",
reinterpret_cast<HOOK>(yadayada_initialize), 2);
3. Destructors in the functions are not called if ruby long jumps out! This
happens when you raise an exception. Here is an example using the classical
Lock-A-Mutex when the object is created, and Unlock-A-Mutex when the
destructor is called:
Lock my_lock(mutex);
connected = rb_iv_get(self, "@connected");
if(connected != Qtrue)
{
rb_raise(rb_eRuntimeError, YadaYada is not connected");
}
When the exception is raised, the destructor of my_lock WILL NOT BE CALLED
so the Mutex is not unlocked. Nasty!
4. You have to #include <string> before <ruby.h>. Otherwise you will get a
lot of compile errors when #include:ing <string>. This might apply to other
include files, but it seemed not to apply to <map> and <list>.
Cheers/D