Question

I'm developing a Ruby-C++ extension. I have to write a non-static method in a CPP class and I have to invoke that class method in ruby client by using the class instance.

Following is the main.cpp:

#include "ruby.h"
#include <iostream>
using namespace std;

class Mclass
{
        public:
        int i;
        static VALUE newMethod(VALUE self);
        static VALUE newInitialize(VALUE self);
};

VALUE Mclass::newMethod(VALUE self)
{
        cout<<"It is newMethod() method of class Mclass"<< endl;
        return Qnil;

}
VALUE Mclass::newInitialize(VALUE self)
{
        cout<<"It is newInitialize() method of class Mclass"<< endl;
        return Qnil;
}

extern "C" void Init_Test(){
   VALUE lemon = rb_define_module("Test");
   VALUE mc = rb_define_class_under(lemon, "Mclass", rb_cObject);
   rb_define_method(mc, "new",
      reinterpret_cast< VALUE(*)(...) >(Mclass::newMethod), 0);
   rb_define_method(mc, "initialize",
      reinterpret_cast< VALUE(*)(...) >(Mclass::newInitialize), 0);
}

Also following is the ruby client code:

require 'Test'
include Test

a = Mclass.new

I'm able to get instance of "Mclass" in ruby client. But want invoke the class non-static method in the ruby client. How can I add the non-static method in CPP class?

Was it helpful?

Solution

You have to wrap your function in C function with C binding. Pass the object (aka this) and all arguments to that C function and call the none static function. You can have a look at https://github.com/TorstenRobitzki/Sioux/blob/master/source/rack/bayeux.cpp, where bayeux_server is a class with a function update_node() that can be called from ruby.

An other good starting point is http://ruby-doc.com/docs/ProgrammingRuby/ chapter "Extending Ruby". Basicaly, you have to make sure, that garbage collector can reach all Ruby objects (VALUEs) that are stored in your own class, or otherwise, the mark and sweep collector will remove them. During your tests, you could manually call the GC to see if some objects get collected that shouldn't get collected.

extern "C" VALUE newInitialize(VALUE self)
{
    MyClass* s = 0;
    Data_Get_Struct( self, MyClass, s );
    s->newInitialize();
}

Don't use reinterpret_cast!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top