如何在基于C的扩展中安全地使用指向Ruby对象的指针?

时间:2012-08-21 15:58:30

标签: c ruby garbage-collection gem

我正在考虑编写一个基于C的Ruby gem来加速Prawn中的文本换行。我以前读过很少一部分用于MRI的C源,但还不知道用于构建扩展的API。

在我的C代码中,我想直接指向Ruby String中的数据,并逐字节地遍历它。除此之外,我想在我自己的struct中将指针存储在缓冲区中,并且不仅在单个调用的范围内使用它们,而且在后续< / em>调用扩展代码。

这可能吗? GC 可以移动字符串,使我的指针无效吗?而且,我怎么能让Ruby知道我在自己的struct中持有指向字符串的指针(所以GC不会尝试回收它们)?这段代码可以用兼容MRI 1.8和1.9的方式编写吗?

因为我要求在基于C的Ruby扩展中安全地使用指针:我可以像在“常规”基于C的项目中那样使用mallocfree吗?

1 个答案:

答案 0 :(得分:2)

matt提供的链接非常好。如果我以前找到它,它本可以节省我的时间。

您可以继续引用ruby字符串和指针。我建议冻结String。然后每次尝试更改字符串都会失败。有一个函数Data_Wrap_Struct(),它允许您将自己的数据结构包装到Ruby对象中。除了数据结构和结构类之外,该函数还有两个函数参数。其中一个(标记)用于显示垃圾收集器,其中您的结构引用其他ruby对象。

我花了一些时间才明白,垃圾收集器实际上正在扫描所有ruby线程的堆栈以寻找对ruby对象的引用。因此,将VALUE保留在堆栈上也是保持引用对象的安全方法。

  

这段代码能否以与MRI 1.8和1.9兼容的方式编写?

扩展的基本API在1.8到1.9之间没有太大变化(我认为)。但到目前为止我只用了1.9。

  

我可以使用malloc并像在“常规”基于C的项目中那样使用它吗?

当然,我想不出有什么理由不可能,只要你不希望垃圾收集器继续关注分配的内存。

我很困难,混合C ++代码,使用另一个版本的gcc编译,而不是编译ruby解释器的版本。如果您遇到奇怪的启动行为,我会检查编译器版本的差异。