如何将C/C++结构绑定到Ruby
How can I bind a C/C++ structure to 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
方法。
相关文章:
- 在基于范围的for循环中使用结构化绑定声明
- 使用结构化绑定'Reflection'
- 为什么结构化绑定不使用"auto&"返回对结构成员的引用,而是返回成员本身
- 为什么 boost::comb 对结构化绑定的支持缺少结构化绑定机制对 boost::tuples::cons 的适应?
- 结构化绑定初始值设定项表单 { 赋值表达式 } 对于 clang 上的数组类型失败
- 在 C++14 中手动实现结构化绑定
- 为什么结构化绑定不支持可变数组?
- 在只读(即 const)访问器上执行结构化绑定的最佳实践是什么?
- 没有类型结构绑定不起作用?
- 对结构成员的临时绑定引用
- 更正GLSL无绑定纹理句柄中的结构布局
- 带有 std::minmax 和 rvalues 的结构化绑定
- 在无序映射的结构化绑定中推导类型
- 为什么基于范围的 for 循环中的结构化绑定只是一个副本而不是引用?
- 您自己的类型的结构化绑定,不是结构或元组(通过公共成员函数)
- 用于基于节点的树结构的Python绑定
- 使用结构绑定更改自定义结构的值
- 结构化绑定:遍历元组的双端面
- 结构绑定:与公共数据成员(继承的基类)结合
- 如何将C/C++结构绑定到Ruby