Forum: Ruby c++ extension

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Gareth R. (Guest)
on 2006-03-09 17:48
I am trying to understand some aspects of writing a ruby extension in
C++.

Actually what I am trying to do is wrap a C++ library and make it
accessible from ruby. Since I have been having problems with the library
that I am trying to wrap, I decided to create a really simple library
and try wrapping that.

The biggest problem that I am having is understanding scope. When I
create the wrapper for the class I create a new instance of the class
that I am wrapping and store it in a ptr. Then when I want to access
methods of this class the wrapper class just delegates to the ptr.
Simple stuff.

When I use a regular ptr things mostly work OK except that I can only
create one instance of the class.

The library I am trying to wrap uses smart pointers, so I created a
version of my code that uses simple pointers. The problem that I have
hear is that these objects then fall out of scope and the destructors
get called immediately after wrapper class method exists. The result of
course is that I get segmentation faults or weird results.

I have only a little experience in C++ and this is my first extension
that I have written.

How should I go about wrapping these c++ classes?

Thanks in advance.

Here is the code....
//extension.cpp
#include <ruby.h>
#include <test.h>
#include <smartptr.h>

typedef VALUE (ruby_method)(...);

auto_ptr<Test> test;
//test* test;

extern "C" VALUE t_TEST_init(VALUE self, VALUE value )
{
        Param * param = new Param( NUM2INT( value ) );
        test = auto_ptr<Test>( new Test( param ) );
        //test = new Test( param );
        return self;
}

extern "C" VALUE t_TEST_value(VALUE self)
{
        return INT2NUM( test->ParamValue() );
}

auto_ptr<Param> param;
//Param* param;

extern "C" VALUE t_PARAM_init(VALUE self, VALUE value )
{
        param = auto_ptr<Param>( new Param( 7 ) );
        //param = new Param( NUM2INT( value ) );
        return self;
}

extern "C" VALUE t_PARAM_value(VALUE self)
{
        return INT2NUM( param->value() );
}


VALUE cTest;
VALUE cParam;

extern "C" void Init_Extension()
{
        cTest = rb_define_class( "Test", rb_cObject );
        rb_define_method( cTest, "initialize", (ruby_method*)
&t_TEST_init, 1 );
        rb_define_method( cTest, "value", (ruby_method*) &t_TEST_value,
0 );

        cParam = rb_define_class( "Param", rb_cObject );
        rb_define_method( cParam, "initialize", (ruby_method*)
&t_PARAM_init, 1 );
        rb_define_method( cParam, "value", (ruby_method*)
&t_PARAM_value, 0 );
}

//test.h
#include <param.h>

class Test {

public:
        Test(Param *);
        ~Test();
        int ParamValue();
private:
        Param *param;

};

//param.h
class Param {

public:
        Param(int);
        ~Param();
        int value();
private:
        int internal;

};
rickhg12hs (Guest)
on 2006-03-10 09:46
(Received via mailing list)
I've been a total wimp about accessing C/C++ libraries from Ruby.  I
haven't done anything particularly hard, but it's always worked.

I use SWIG (www.swig.org).  The most I've had to do is write a couple
helper functions and that's about it.  SWIG even comes with some
helpful Ruby examples, extconf.rb skeletons, and Makefile skeltons.
The SWIG documentation has a couple of sections on smart pointers.
While I was learning to use SWIG, their community was helpful with Ruby
specific suggestions.

Let us know how you do.  Good Luck!
Caleb T. (Guest)
on 2006-03-10 14:04
(Received via mailing list)
>
> How should I go about wrapping these c++ classes?

You need to wrap your class into a Ruby structure in order for this
to work right.

See: Data_Wrap_Struct and Data_Make_Struct for details

I'm not sure the implications of using an auto_ptr in the mix...as
I've never tried it.  But, if you use the above methods you don't
need it since Ruby will handle the lifetime of your object for you
(and provide a garbage collection hook for your destructor).
This topic is locked and can not be replied to.