我一直在阅读有关如何将Ruby嵌入到C ++程序中的教程。我已经找到了如何通过“rb_define_class”和“rb_define_class_under”定义一个类,以及通过“rb_define_method”定义一个类。现在我需要一个很好的例子来解释如何使用C ++编写的ruby类包装现有的C ++对象(指针)。例如:
class MyClass
{
public:
MyClass();
void MyMethod();
};
VALUE myclass_init(VALUE self)
{
// I'd like to create a new MyClass instance and store its pointer inside "self"
}
VALUE myclass_meth(VALUE self)
{
// Now i need to retrieve the pointer to the object and call its method
}
int main(int argc, char* argv[])
{
ruby_init();
ruby_init_loadpath();
VALUE myclass = rb_define_class("MyWrapperClass", rb_cObject);
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;
}
我还需要一种方法来处理垃圾收集,以释放我的包装对象(以及做其他事情)。对不起英语不好,感谢任何试图回答这个问题的人!
答案 0 :(得分:3)
要与Ruby的内存管理集成,您需要实现两个为您的一个对象分配和释放内存的函数 - 两者都不需要参数。 Ruby会将您的C ++数据结构“附加”到Ruby self
VALUE,您需要使用几种方法来创建该附件,并从self
获取C ++。
到目前为止,您的代码足够接近我刚刚填补了您的空白:
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;
}