rb_iv_get和rb_iv_setVS。Data_Wrap_Struct用于定制cals因此,在阅读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.
}
Run Code Online (Sandbox Code Playgroud)
其次,someValue_get_Customand 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;?
}
Run Code Online (Sandbox Code Playgroud)
另一个选择是创建一个C版本,attr_accessor该版本会使代码和DRYer略短一些,但仍将是计划B的一部分(使用rb_iv_ set/ get)。
现在,我真的很想弄清楚如何使用Data_Wrap_Struct,因为我怀疑它可能比使用rb_iv_setand 更快rb_iv_get,但是如果不是我认为的那样,那么我将不得不求助于计划B。
所以,我想真正的问题是:
什么确切确实Data_Wrap_Struct做以及如何正确地使用它,或者just用它不示数。
哦,我差点忘了,还有几个有关的问题Data_Wrap_Struct:
mark参数(一个函数)到底做什么?它说如果未在任何地方引用该对象,则将mark参数设置为0,但是如果在某个地方(可能是RArray)进行引用怎么办?
其次,free参数(也是一个函数)是否是一个简单的函数,可以为该对象释放分配的内存?
垃圾收集器是否将任何东西传递给这两个功能,也许是VALUE self?
谢谢!
这些问题很多,我将尝试用几句话回答。
可以将其Data_Wrap_Struct视为一个薄的Ruby包装器,在Ruby中可以看到它是一个“普通”对象,但实际上在其底层有一个C结构的引用(理论上可以是任何东西,但对于复杂类型才有意义)。这样的想法是,您可以将结构附加到Ruby对象,并且只要Ruby通过将消息发送到该包装对象来请求结构数据,就可以随时访问该结构数据。然后在C语言中,从结构中检索数据,将其转换为红宝石色,然后将其传递回去。或者,当要求您在包装对象中设置数据时,您做相反的事情-将Ruby数据转换为适合该结构的数据。
当垃圾收集器决定收集包装对象时,它还希望释放底层的C结构-这是free参数的工作,它是指向将结构类型作为参数的函数的函数指针,并应释放该结构的内存。
该mark参数是一个复杂多了,我建议你张贴此作为一个单独的问题。好东西:大多数时候您不需要它。
rb_iv_get,rb_iv_set以及rb_ivar_get和rb_ivar_set的目的完全不同。他们设置了Ruby对象的实例变量,而我猜这就是您真正想要的。这里的重点是您在这里获取/设置VALUEs,即您在这里使用Ruby对象而不是普通的C类型。
您无需编写C的C版本attr_accessor,它已经存在:rb_attr。
总结一下:Data_Wrap_Struct将容器对象包装在C结构上,但除此之外还没有提供任何功能。如果您打算具有功能,则应rb_attr在Init方法中使用attr_accessor。使用rb_iv*,如果你真的想设置或获取实例变量explicitly.`
我同意缺少关于如何为Ruby编写C扩展的确切资源。但是,有很多博客文章。根据我自己的经验,我可能会从Serabe在评论中提到的Pickaxe PDF开始,并且在Ruby源代码(README.EXT)中实际上有一个非常简洁的介绍。之后,您最好的办法是查看extRuby源代码中目录中的扩展名。选择一个您熟悉或喜欢的功能并使用它。始终准备好Ruby源代码。如果您不知道某个特定函数的功能,请在源代码中查找其声明,以至少对它的功能有所了解。您不需要乍一看就了解所有内容,但是通常它给您足够的能力来完成您的任务。