如何将C/C++结构绑定到Ruby



我需要一些关于如何将C/C++结构绑定到Ruby的建议。我读了一些手册,发现了如何将类方法绑定到类,但我仍然不明白如何绑定结构字段并使它们在Ruby中可访问。

这是我正在使用的代码:

myclass = rb_define_class("Myclass", 0);
...
typedef struct nya
{
    char const* name;
    int age;
} Nya;
Nya* p;
VALUE vnya;
p = (Nya*)(ALLOC(Nya));
p->name = "Masha";
p->age = 24;
vnya = Data_Wrap_Struct(myclass, 0, free, p);
rb_eval_string("def foo( a ) p a end"); // This function should print structure object
rb_funcall(0, rb_intern("foo"), 1, vnya); //  Here I call the function and pass the object into it

Ruby函数似乎假定a是一个指针。它打印指针的数值,而不是它的实际内容(即["Masha", 24])。显然Ruby函数无法识别这个对象—我没有设置对象的属性名称和类型。

我该怎么做?不幸的是,我想不通。

您已经将指针封装在Ruby对象中。现在,您所要做的就是定义如何从Ruby世界访问它:

/* Feel free to convert this function to a macro */
static Nya * get_nya_from(VALUE value) {
    Nya * pointer = 0;
    Data_Get_Struct(value, Nya, pointer);
    return pointer;
}
VALUE nya_get_name(VALUE self) {
    return rb_str_new_cstr(get_nya_from(self)->name);
}
VALUE nya_set_name(VALUE self, VALUE name) {
    /* StringValueCStr returns a null-terminated string. I'm not sure if
       it will be freed when the name gets swept by the GC, so maybe you
       should create a copy of the string and store that instead. */
    get_nya_from(self)->name = StringValueCStr(name);
    return name;
}
VALUE nya_get_age(VALUE self) {
    return INT2FIX(get_nya_from(self)->age);
}
VALUE nya_set_age(VALUE self, VALUE age) {
    get_nya_from(self)->age = FIX2INT(age);
    return age;
}
void init_Myclass() {
    /* Associate these functions with Ruby methods. */
    rb_define_method(myclass, "name",  nya_get_name, 0);
    rb_define_method(myclass, "name=", nya_set_name, 1);
    rb_define_method(myclass, "age",   nya_get_age,  0);
    rb_define_method(myclass, "age=",  nya_set_age,  1);
}

既然您可以访问您的结构中包含的数据,那么您可以简单地在Ruby中定义高级方法:

class Myclass
  def to_a
    [name, age]
  end
  alias to_ary to_a
  def to_s
    to_a.join ', '
  end
  def inspect
    to_a.inspect
  end
end

供参考:README.EXT

这不是关于结构问题的直接答案,但它是将C++类移植到Ruby问题的通用解决方案。

您可以使用SWIG来包装C/C++类、结构和函数。就建筑而言,它是在烧房子来煎鸡蛋。但是,如果您需要一个工具来将C++类快速转换为Ruby(以及其他20种语言),SWIG可能会对您有用。

在涉及结构的情况下,您只需要创建一个.i文件,其中包括(在最简单的情况下)行#include <your C++ library.h>

附言:再一次,这不是对涉及这个结构的问题的直接回答,但也许你可以使用一个更通用的解决方案,在这种情况下,这可能会对你有所帮助。

另一个选项是使用RubyOnline-它对转换C和Ruby类型(如int、char*和float)的支持有限,而且它还支持访问C结构-请参阅API中的accessor方法。

最新更新