# Coding Ruby Extension with C++ on Win32

**URL:** <https://www.ruby-forum.com/t/coding-ruby-extension-with-c-on-win32/127322>\
**Category:** Ruby\
**Created:** [January 28, 2008, 8:53am UTC](https://www.ruby-forum.com/t/coding-ruby-extension-with-c-on-win32/127322 "2008-01-28T08:53:08Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![daniel\_SSSSkerud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e8cbc/32.png) [@daniel\_SSSSkerud](https://www.ruby-forum.com/u/daniel_SSSSkerud)\
**Post date:** [January 28, 2008, 8:53am UTC](https://www.ruby-forum.com/t/coding-ruby-extension-with-c-on-win32/127322/1 "2008-01-28T08:53:08Z")

</div>

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(yadayada\_initialize), 2);

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

1. You have to #include before \<ruby.h\>. Otherwise you will get  
a  
lot of compile errors when #include:ing . This might apply to  
other  
include files, but it seemed not to apply to and .

Cheers/D

---

<div class="post-metadata">

**Author:** ![daniel\_SSSSkerud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e8cbc/32.png) [@daniel\_SSSSkerud](https://www.ruby-forum.com/u/daniel_SSSSkerud)\
**Post date:** [January 28, 2008, 4:40pm UTC](https://www.ruby-forum.com/t/coding-ruby-extension-with-c-on-win32/127322/2 "2008-01-28T16:40:43Z")

</div>

On Mon, 28 Jan 2008 02:50:39 -0500, daniel Ã¥kerud wrote:

> not “.c” so that they are compiled as c++ files instead of c files.  
> rb\_define\_method(rb\_cYadaYada, “initialize”,
> 
> other include files, but it seemed not to apply to and .
> 
> Cheers/D

Try writing the whole OO interface in C++, and letting SWIG do the  
mapping into ruby for you. SWIG knows (with appropriate includes) about  
std::vector (which maps to Array) and std::string (which maps to  
String).

–Ken

---

<div class="post-metadata">

**Author:** ![daniel\_SSSSkerud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8e8cbc/32.png) [@daniel\_SSSSkerud](https://www.ruby-forum.com/u/daniel_SSSSkerud)\
**Post date:** [February 21, 2008, 3:45pm UTC](https://www.ruby-forum.com/t/coding-ruby-extension-with-c-on-win32/127322/3 "2008-02-21T15:45:51Z")

</div>

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(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](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).

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

> 1. You have to #include before \<ruby.h\>. Otherwise you will get a  
> lot of compile errors when #include:ing . This might apply to other  
> include files, but it seemed not to apply to and .

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

Paul
