C++ DLL example

Can someone point me to a simple example of calling a C++ function from Ruby?
I know how to do it with SWIG, but I'm trying to learn how to do it
without SWIG.
I'd like to do this under Windows and have the C++ code in a DLL.
No Windows APIs will be invoked. I just want to do something simple in
C++ like this

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

and invoke the greet function from Ruby.

I know how to build a DLL using VC++ 8.
I suspect the issue is that I don't have the right setup in my .cpp file.

···

--
R. Mark Volkmann
Partner, Object Computing, Inc.

The way I do it is to make sure all entry points in the C++ file are extern "C"
and create a C wrapper file that calls the C++ funcs which have C linkage.
Then I run extconf.rb for this wrapper file to create a Ruby extension makefile.
I picked most of this up from Pickax I, "Extending Ruby."

Also, for some reason I cannot fathom, I had to replace all C++ I/O with C I/O
routines. After doing that, I was able to compile the C++ file, then compile the
C extension and properly link everything together as long as I remembered to add
-lstdc++ as a link option. I always link to either a .a or a .o so I don't know
how well this applies to a dll.

This was all done with Windows XP / Cygwin / gcc, so my particulars probably do
not apply to your situation, but the overall plan of attack could be applied.

BTW, you wont be able to link to a 'static' function. It would be better to
rewrite it like this:

.cpp file:
extern "C" void greet(char *name) {
    // C++ stuff here

    printf( "Hello %s\n", name );
}

and then I would create a standard .c wrapper file for this, where the
Ruby extension initialization code is put.

Mark Volkmann wrote:

···

Can someone point me to a simple example of calling a C++ function from Ruby?
I know how to do it with SWIG, but I'm trying to learn how to do it
without SWIG.
I'd like to do this under Windows and have the C++ code in a DLL.
No Windows APIs will be invoked. I just want to do something simple in
C++ like this

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

and invoke the greet function from Ruby.

I know how to build a DLL using VC++ 8.
I suspect the issue is that I don't have the right setup in my .cpp file.

--
R. Mark Volkmann
Partner, Object Computing, Inc.

Hi Mark,

it's not that hard, your cpp file should/could look like this:

···

---------------------------------------------------------------------
#include "ruby.h"
#include <string>
#include <iostream>

using namespace std;

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

static VALUE rb_greet(VALUE self, VALUE name){
  greet(STR2CSTR(name));
  return Qnil;
}

void Init_RubyDll() {
  rb_define_global_function("greet", (VALUE(*)(ANYARGS))rb_greet, 1);
}
---------------------------------------------------------------------

Add this to a new dll project, add the path to ruby.h to the project
settings and link against msvcrt-ruby18.lib.

Finally you have to export the Init_XXX (XXX has to be equal to the name
of your Dll) function. I usually add a /EXPORT:Init_RubyDll to the
command line options of the linker.

After doing so i could execute

C:\>ruby -e "require 'RubyDll'; greet 'Mark '"
Hello Mark

Hope that helps.

cheers

Simon

p.s.: one gotcha left: The ruby in the one-click-installer is compiled
with vc6, linking to libs from another version might be risky.

Mark Volkmann schrieb:

Can someone point me to a simple example of calling a C++ function from Ruby?
I know how to do it with SWIG, but I'm trying to learn how to do it
without SWIG.
I'd like to do this under Windows and have the C++ code in a DLL.
No Windows APIs will be invoked. I just want to do something simple in
C++ like this

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

and invoke the greet function from Ruby.

I know how to build a DLL using VC++ 8.
I suspect the issue is that I don't have the right setup in my .cpp file.

--
R. Mark Volkmann
Partner, Object Computing, Inc.

Mark Volkmann wrote:

Can someone point me to a simple example of calling a C++ function from
Ruby?
I know how to do it with SWIG, but I'm trying to learn how to do it
without SWIG.
I'd like to do this under Windows and have the C++ code in a DLL.
No Windows APIs will be invoked. I just want to do something simple in
C++ like this

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

and invoke the greet function from Ruby.

I know how to build a DLL using VC++ 8.
I suspect the issue is that I don't have the right setup in my .cpp
file.

I had a question on C++ extensions that contained some code examples.
Its here C++ extension - Ruby - Ruby-Forum.

Gareth

···

--
Posted via http://www.ruby-forum.com/\.

Thanks for the detailed instructions Simon!

I'm trying to build my DLL with Visual C++ 2005 Express Edition which
is free. I saw your warning about the possibility that this won't work
because the one-click installer is compiled with VC6. I'm not able to
get to the point to test that though. I'm getting a compile error that
says win32.h needs windows.h and it can't find that. I searched my
entire hard drive for windows.h and only found one under my cygwin
directory. I don't want to use that one because I want to find a
solution that doesn't assume cygwin is installed. Any idea why it's
looking for windows.h and where it should be?

···

On 3/11/06, Simon Kröger <SimonKroeger@gmx.de> wrote:

Hi Mark,

it's not that hard, your cpp file should/could look like this:

---------------------------------------------------------------------
#include "ruby.h"
#include <string>
#include <iostream>

using namespace std;

static void greet(const string& name) {
  cout << "Hello " << name << endl;
}

static VALUE rb_greet(VALUE self, VALUE name){
  greet(STR2CSTR(name));
  return Qnil;
}

void Init_RubyDll() {
  rb_define_global_function("greet", (VALUE(*)(ANYARGS))rb_greet, 1);
}
---------------------------------------------------------------------

Add this to a new dll project, add the path to ruby.h to the project
settings and link against msvcrt-ruby18.lib.

Finally you have to export the Init_XXX (XXX has to be equal to the name
of your Dll) function. I usually add a /EXPORT:Init_RubyDll to the
command line options of the linker.

After doing so i could execute

C:\>ruby -e "require 'RubyDll'; greet 'Mark '"
Hello Mark

Hope that helps.

cheers

Simon

p.s.: one gotcha left: The ruby in the one-click-installer is compiled
with vc6, linking to libs from another version might be risky.

Mark Volkmann schrieb:
> Can someone point me to a simple example of calling a C++ function from Ruby?
> I know how to do it with SWIG, but I'm trying to learn how to do it
> without SWIG.
> I'd like to do this under Windows and have the C++ code in a DLL.
> No Windows APIs will be invoked. I just want to do something simple in
> C++ like this
>
> static void greet(const string& name) {
> cout << "Hello " << name << endl;
> }
>
> and invoke the greet function from Ruby.
>
> I know how to build a DLL using VC++ 8.
> I suspect the issue is that I don't have the right setup in my .cpp file.
>
> --
> R. Mark Volkmann
> Partner, Object Computing, Inc.
>
>

--
R. Mark Volkmann
Partner, Object Computing, Inc.