rb_iv_get
和rb_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_Custom
和someValue_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_set
和rb_iv_get
更快,但如果不是我的话认为是的,那么我将不得不诉诸B计划。
所以,我猜真正的问题是:
完全 Data_Wrap_Struct
做了什么,以及如何正确使用它,或just
使用它而不会出错。
哦,我差点忘了,还有一些与Data_Wrap_Struct
相关的问题:
标记参数(函数)到底有什么作用?如果没有在任何地方引用对象,它会将mark参数设置为0,但是如果它被引用到某处(可能是RArray)会怎样?
其次,free参数(也是一个函数)是一个简单的函数,可以释放该对象的已分配内存吗?
垃圾收集器是否传递给这两个函数,可能是VALUE self
?
谢谢!
答案 0 :(得分:4)
这些是很多问题,我会尝试用几句话回答那些我能回答的问题。
将Data_Wrap_Struct
视为一个瘦的Ruby包装器,它在Ruby中可见为“普通”对象,但实际上带有对C结构的引用(可能是理论上的任何东西,但对于复杂类型才有意义在它的引擎盖下。我们的想法是,通过这种方式,您可以将结构附加到Ruby对象,并且只要Ruby通过向该包装器对象发送消息来请求它,就可以随时访问结构数据。在C中,然后从结构中检索数据,将其转换为rubyish并将其传回。或者,当您被要求在包装器对象中设置数据时,您会反过来 - 将Ruby数据转换为适合结构的数据。
当垃圾收集器决定收集包装器对象时,它还想释放底层的C结构 - 这是free
参数的作用,它是一个函数指针,指向一个将结构类型作为一个函数的函数。参数,应该释放该结构的记忆。
mark
参数要复杂得多,我建议您将此作为单独的问题发布。好事:大多数时候你不需要它。
rb_iv_get
,rb_iv_set
以及rb_ivar_get
和rb_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源代码。如果您不知道某个特定函数的作用,请在源代码中查看其声明,以至少了解它的作用。乍一看,你不需要了解它,但它通常足以让你继续完成任务。