The Programming Ruby book is one of those must have references if you’re going to program Ruby. I still use it all the time when I’m looking up information on Ruby. One thing I’ve started playing with is getting a C extension to work with Ruby. Chapter 21 of Volume 2 of Programming Ruby gives you a great example for writing a C extension from scratch and getting it to compile and work in a UNIX-based environment however it falls short on handholding you through the Windows process. Here’s my notes on what you need:
- Install Visual Studio Express or some other Visual C++ variant
- Install the Platform SDK (You need this if you want windows.h and you DO)
- Make minor changes in Ruby config.h (Not necessary for all versions of Visual Studio)
- Write the MyTest code and extconf.rb file from the book
- Run ruby extconf.rb to generate a nmake-based Makefile
- Startup a command prompt with the SDK environment variables set
- Run nmake to compile the library
The detailed version
Download Visual Studio
Unless you’re using cygwin or mingw as your compiler you’ll probably want to get Visual Studio. The latest incarnation is Visual Studio 2005 which is a free download. I’ve found that it’s a pain to find the right URL to download it from on Microsoft but that’s Microsoft for you.
Download the Windows Platform SDK
Since the Windows version of Ruby ties in with many Win32 libraries it’s necessary to get the Platform SDK. If you DON’T download it you will see strange error messages when trying to compile your Ruby extension such as this:
c:\ruby\lib\ruby\1.8\i386-mswin32\win32/win32.h(32) : fatal error C1083: Cannot open include file: 'windows.h': No such file or directory NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 8\VC\BIN\cl.EXE"' : return code '0x2' Stop.
windows.h is NOT included by default in Visual Studio 2005 (but I believe it is in older versions of Visual Studio) so you need the platform SDKs to get the right development libraries. While it would be nice if the C-based version of Ruby could easily hook into the .Net platform, this would probably require significant hacking the mkmf library in Ruby to get it to work transparently. I doubt that will happen soon.
Once again, I found Microsoft’s website really annoying to navigate in order to try to find the Platform SDK so you might want to click here then make sure you have the latest platform SDK (As of this writing the latest was R1)
For some versions Visual Studio (noteably Visual Studio 2005), the config file located in $RUBY_HOME/lib/ruby/1.8/i386-mswin32/config.h (Usually $RUBY_HOME installs to C:/Ruby) will require a tweak to allow compilation. Or you could rebuild Ruby from scratch yourself but I prefer to use the All-in-one installer. In the config.h file delete or comment out the following lines:
#if _MSC_VER != 1200 #error MSC version unmatch #endif
Finally! Let’s compile it already
Okay now you’re ready to finally to actually compile your code. In order to get all the environment variables set properly you might want to launch a command prompt from the shortcuts the Platform SDK makes in the Start Menu then make sure to run vsvars32.bat from Visual Studio’s directory (Usually in C:\Program Files\Microsoft Visual Studio 8\VC\bin). Now with that all set you can finally compile something! (whew!):
C:\cygwin\home\foo\exttest>ruby extconf.rb creating Makefile C:\cygwin\home\foo\exttest>nmake Microsoft (R) Program Maintenance Utility Version 8.00.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. cl -nologo -I. -Ic:/ruby/lib/ruby/1.8/i386-mswin32 -Ic:/ruby/lib/ruby/1. 8/i386-mswin32 -I. -MD -Zi -O2b2xg- -G6 -c -Tcmy_test.c cl : Command line warning D9035 : option 'Og-' has been deprecated and will be r emoved in a future release cl : Command line warning D9002 : ignoring unknown option '-G6' my_test.c cl -nologo -LD -Femy_test.so my_test.obj msvcrt-ruby18.lib oldnames.lib user32.lib advapi32.lib wsock32.lib -link -incremental:no -debug -opt:ref -opt :icf -dll -libpath:"c:/ruby/lib" -def:my_test-i386-mswin32.def -implib:my_test-i 386-mswin32.lib -pdb:my_test-i386-mswin32.pdb Creating library my_test-i386-mswin32.lib and object my_test-i386-mswin32.exp C:\cygwin\foo\exttest>irb irb(main):001:0> require 'my_test' => true irb(main):002:0> test = MyTest.new => #