On Mon, Jan 28, 2008 at 04:50:39PM +0900, daniel ?kerud wrote:
> // first a typedef
> typedef VALUE (*HOOK)(...);
> // then do a reinterpret_cast:
> rb_define_method(rb_cYadaYada, "initialize",
> reinterpret_cast<HOOK>(yadayada_initialize), 2);

The problem is not that the methods are static; it's that they don't
have the same signature as the rb_define_method function expects.  You
can cast to the right type using the RUBY_METHOD_FUNC() macro (this is
what Rice does - see http://rice.rubyforge.org - though it doesn't work
with a compiler as old as VC6).

Some compilers also check the calling convention (e.g. comeau).
Unfortunately, C++ provides no mechanism to specify both the calling
convention *and* the linkage, so if your compiler uses a different
calling convention for C and C++ code, you *have* to make your wrapper
functions extern "C" (which is a nuisance, since it means it's
impossible to have internal linkage and C calling convention on such
compilers).

> 3. Destructors in the functions are not called if ruby long jumps out! This
> happens when you raise an exception.

IIRC the C++ standard does not specify what happens if you longjmp over
code with objects on the stack that have destructors with non-trivial
behavior.  In other words, your destructor might get called, or it might
not.

The solution here is to use rb_protect whenever you call into Ruby code.
This is what Rice does under the hood.

There's a similar problem with allowing C++ exceptions to escape into
Ruby-land; on most compilers I've used, this causes std::terminate to
get called.

> 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>.

I've not experienced this problem.  What kinds of errors do you get?

Paul