rb_iv_get和rb_iv_set VS. Data_Wrap_Struct用于创建自定义类

时间:2011-08-15 17:28:13

标签: c ruby

rb_iv_getrb_iv_set VS. Data_Wrap_Struct用于自定义calsses

因此,阅读Ruby Extension API,我发现Data_Wrap_Struct将指针转换为Ruby对象(对吗?)。但是,当我尝试使用时,我不断得到随机错误和诸如此类的东西,所以我有点像切换到类似的东西:

void Init_custom() {
    //cCustom declared as VALUE higher in the code
    cCustom = rb_define_class("Custom", T_OBJECT);
    rb_define_method(mTester, "initialize", init_Custom, 1);
    rb_define_method(mTester, "someValue", someValue_get_Custom, 0);
    rb_define_method(mTester, "someValue=", someValue_set_Custom, 1);
    //And so on.
}

其次someValue_get_CustomsomeValue_set_Custom将是:

VALUE someValue_get_Custom(VALUE self) {
    return rb_iv_get(self, "@someValue")
}

VALUE someValue_set_Custom(VALUE self, VALUE val) {
    return rb_iv_set(self, "@someValue", val) //or do I have to do return val;?
}

另一种选择是创建attr_accessor的C版本,这会使代码略微缩短并且干扰,但它仍然是计划B的一部分(使用rb_iv_ set / get)。


现在,我真的很想弄清楚如何使用Data_Wrap_Struct,因为我怀疑它可能比使用rb_iv_setrb_iv_get更快,但如果不是我的话认为是的,那么我将不得不诉诸B计划。

所以,我猜真正的问题是:

完全 Data_Wrap_Struct做了什么,以及如何正确使用它,或just使用它而不会出错


哦,我差点忘了,还有一些与Data_Wrap_Struct相关的问题:

标记参数(函数)到底有什么作用?如果没有在任何地方引用对象,它会将mark参数设置为0,但是如果它被引用到某处(可能是RArray)会怎样?

其次,free参数(也是一个函数)是一个简单的函数,可以释放该对象的已分配内存吗?

垃圾收集器是否传递给这两个函数,可能是VALUE self

谢谢!

1 个答案:

答案 0 :(得分:4)

这些是很多问题,我会尝试用几句话回答那些我能回答的问题。

Data_Wrap_Struct视为一个瘦的Ruby包装器,它在Ruby中可见为“普通”对象,但实际上带有对C结构的引用(可能是理论上的任何东西,但对于复杂类型才有意义在它的引擎盖下。我们的想法是,通过这种方式,您可以将结构附加到Ruby对象,并且只要Ruby通过向该包装器对象发送消息来请求它,就可以随时访问结构数据。在C中,然后从结构中检索数据,将其转换为rubyish并将其传回。或者,当您被要求在包装器对象中设置数据时,您会反过来 - 将Ruby数据转换为适合结构的数据。

当垃圾收集器决定收集包装器对象时,它还想释放底层的C结构 - 这是free参数的作用,它是一个函数指针,指向一个将结构类型作为一个函数的函数。参数,应该释放该结构的记忆。

mark参数要复杂得多,我建议您将此作为单独的问题发布。好事:大多数时候你不需要它。

rb_iv_getrb_iv_set以及rb_ivar_getrb_ivar_set的目的完全不同。他们设置了Ruby对象的实例变量,我的猜测就是你实际上在寻找的东西。这里的要点是你在这里获得/设置VALUE,即你在这里使用Ruby对象而不是普通的C类型。

您不必编写attr_accessor的C版本,它已经存在:rb_attr

总结一下:Data_Wrap_Struct将一个容器对象包装在你的C结构上,但除此之外还没有提供任何功能。如果您打算使用rb_attr功能,则应在Init方法中使用attr_accessor。如果您确实想要明确设置或获取实例变量,请使用rb_iv*


我同意如何为Ruby编写C扩展缺乏明确的资源。但是,有很多博客文章。根据我自己的经验,我可能会从Serabe在评论中提到的Pickaxe PDF开始,并且在Ruby源代码中有一个非常简洁的介绍(README.EXT)。之后,您可以做的最好的事情是查看Ruby源代码中ext目录中的扩展。选择一个您熟悉的或您喜欢的功能并使用它。始终掌握Ruby源代码。如果您不知道某个特定函数的作用,请在源代码中查看其声明,以至少了解它的作用。乍一看,你不需要了解它,但它通常足以让你继续完成任务。