3

我正在考虑编写一个基于 C 的 Ruby gem 来加速Prawn中的文本换行。我之前读过一小部分 MRI 的 C 源代码,但还不了解用于构建扩展的 API。

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

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

既然我问的是在基于 C 的 Ruby 扩展中安全地使用指针:我可以像在“常规”基于 C 的项目中一样使用malloc和吗?free

4

1 回答 1

2

马特提供的链接非常好。如果我以前找到它,它会节省我几天的时间。

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

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

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

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

我可以像在“常规”基于 C 的项目中一样使用 malloc 和 free 吗?

当然,我想不出任何为什么这不可能,只要您不期望垃圾收集器来处理分配的内存。

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

于 2012-08-22T06:06:39.363 回答