To integrate with Ruby's memory management, you need to implement two functions that allocate and free memory for one of your objects - neither may take parameters. Ruby will store your C++ data structure "attached" to the Ruby self
VALUE, and you need to use a couple of methods to create that attachment, and to get at your C++ from self
.
Your code so far was close enough that I have just filled in the gaps for you here:
class MyClass
{
public:
MyClass();
void MyMethod();
};
//////////////////////////////////////////////////////////
// The next five are the functions that you were missing
// (although you could factor this differently if you chose)
MyClass *rb_create_myclass_obj() {
return new MyClass();
}
void rb_delete_myclass_obj( MyClass *p_myclass ) {
delete p_myclass;
return;
}
VALUE myclass_as_ruby_class( MyClass *p_myclass , VALUE klass ) {
return Data_Wrap_Struct( klass, 0, rb_delete_myclass_obj, p_myclass );
}
VALUE myclass_alloc(VALUE klass) {
return myclass_as_ruby_class( rb_create_myclass_obj(), klass );
}
MyClass *get_myclass_obj( VALUE obj ) {
MyClass *p_myclass;
Data_Get_Struct( obj, MyClass, p_myclass );
return p_myclass;
}
//////////////////////////////////////////////////////////
VALUE myclass_init(VALUE self)
{
// You need do nothing here, Ruby will call myclass_alloc for
// you.
return self;
}
VALUE myclass_meth(VALUE self)
{
MyClass *p_myclass = get_myclass_obj( self );
p_myclass->MyMethod();
// If MyMethod returns some C++ structure, you will need to convert it
// Here's how to return Ruby's nil
return Qnil;
}
int main(int argc, char* argv[])
{
ruby_init();
ruby_init_loadpath();
VALUE myclass = rb_define_class("MyWrapperClass", rb_cObject);
// The alloc function is how Ruby hooks up the memory management
rb_define_alloc_func(myclass, myclass_alloc);
rb_define_method(myclass, "initialize", (VALUE(*)(...))myclass_init, 0);
rb_define_method(myclass, "myWrappedMethod", (VALUE(*)(...))myclass_meth, 0);
// Loading ruby script skipped..
ruby_finalize();
return 0;
}