简体   繁体   English

在Ruby和C ++之间交换数据

[英]Exchanging data between Ruby and C++

I've been looking through tutorials on how to embed Ruby into a C++ program. 我一直在浏览有关如何将Ruby嵌入C ++程序的教程。 I've found out how to define a class through "rb_define_class" and "rb_define_class_under" and methods through "rb_define_method". 我发现了如何通过“ rb_define_class”和“ rb_define_class_under”定义一个类以及如何通过“ rb_define_method”定义方法。 Now i need a good example that explains how to wrap an existing C++ object (pointer) with a ruby class written in C++. 现在,我需要一个很好的示例,说明如何用用C ++编写的ruby类包装现有的C ++对象(指针)。 Example: 例:

    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;
    }

I also need a way to handle garbage collection in order to free my wrapped object (and do other stuff). 我还需要一种方法来处理垃圾回收,以释放包装好的对象(并执行其他操作)。 Sorry for the bad english and thanks to whoever will try to answer this question! 对不起,英语不好,谢谢任何尝试回答这个问题的人!

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的内存管理集成,您需要实现两个函数来为您的一个对象分配和释放内存-两个都不能使用参数。 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 . Ruby将存储“附加”到Ruby self VALUE的C ++数据结构,您需要使用几种方法来创建该附件,并从self获取C ++。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM