将 glib 绑定到 Crystal lang(GC 问题)
Binding glib into Crystal lang (GC issue)
我正在尝试将一些函数从 glib 绑定到 Crystal。我已经这样做了并且有效:
@[Link("glib-2.0")]
lib LibG
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
end
但是它引入了内存泄漏:使用 g_* 函数创建的对象永远不会被垃圾收集。
在Crystal中是否可以让 glib 与 Boehm GC 很好地配合?受到 PCRE 的启发,我试过了:
@[Link("glib-2.0")]
lib LibG
# These 2 functions work perfectly
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
alias Malloc = LibC::SizeT -> Void*
alias Free = Void* ->
$g_malloc : Malloc
$g_free : Free
end
# At this point happens segmentation fault
LibG.g_malloc = ->GC.malloc(LibC::SizeT)
LibG.g_free = ->GC.free(Void*)
希望override/redefineg_malloc
和g_free
功能。
但它没有成功:它因分段错误而失败。
关于如何让 glib 使用 GC 有什么想法吗?
我发现了某种相关的问题,但对我没有帮助:Garbage collection with glib?
提前致谢。
为此,我建议使用 gobject-introspection。它为每个库提供了一个 .GIR 文件,这是一个很大的 XML 文件,描述了库中每个函数的 API、class 和方法,以及如何为每个输入处理内存和输出参数。您可以使用它为 GLib 等库动态生成绑定。
它还提供了一个广泛的单元测试库,您可以使用它来检查您的绑定是否正常工作。
至于内存管理,覆盖g_malloc
和g_free
好像是自找麻烦。在 JavaScript 的 gobject-introspection 绑定中完成的等效方法是始终确保 JS 环境拥有内存。例如,对于从 C 函数返回的字符串;如果返回的字符串的所有权给了调用者,那么从返回的字符串创建一个 JS 字符串(它复制字符串)并释放返回的字符串。如果库保留返回字符串的所有权,则会创建一个 JS 字符串并且不会释放返回的字符串。在这两种情况下,唯一使用的内存由 JS 环境拥有,并受 JS 的垃圾收集器的约束。
GLib 对象是另一回事,因为它们是引用计数的,所以 JS 包装器对象可以简单地保存对它们的引用;当 JS 对象被 GC 时,它会释放它的引用,如果没有其他 JS 对象持有它,C 对象也会被销毁。
我正在尝试将一些函数从 glib 绑定到 Crystal。我已经这样做了并且有效:
@[Link("glib-2.0")]
lib LibG
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
end
但是它引入了内存泄漏:使用 g_* 函数创建的对象永远不会被垃圾收集。
在Crystal中是否可以让 glib 与 Boehm GC 很好地配合?受到 PCRE 的启发,我试过了:
@[Link("glib-2.0")]
lib LibG
# These 2 functions work perfectly
fun g_utf8_strup(str : UInt8*, len : UInt32) : UInt8*
fun g_utf8_strdown(str : UInt8*, len : UInt32) : UInt8*
alias Malloc = LibC::SizeT -> Void*
alias Free = Void* ->
$g_malloc : Malloc
$g_free : Free
end
# At this point happens segmentation fault
LibG.g_malloc = ->GC.malloc(LibC::SizeT)
LibG.g_free = ->GC.free(Void*)
希望override/redefineg_malloc
和g_free
功能。
但它没有成功:它因分段错误而失败。
关于如何让 glib 使用 GC 有什么想法吗? 我发现了某种相关的问题,但对我没有帮助:Garbage collection with glib?
提前致谢。
为此,我建议使用 gobject-introspection。它为每个库提供了一个 .GIR 文件,这是一个很大的 XML 文件,描述了库中每个函数的 API、class 和方法,以及如何为每个输入处理内存和输出参数。您可以使用它为 GLib 等库动态生成绑定。
它还提供了一个广泛的单元测试库,您可以使用它来检查您的绑定是否正常工作。
至于内存管理,覆盖g_malloc
和g_free
好像是自找麻烦。在 JavaScript 的 gobject-introspection 绑定中完成的等效方法是始终确保 JS 环境拥有内存。例如,对于从 C 函数返回的字符串;如果返回的字符串的所有权给了调用者,那么从返回的字符串创建一个 JS 字符串(它复制字符串)并释放返回的字符串。如果库保留返回字符串的所有权,则会创建一个 JS 字符串并且不会释放返回的字符串。在这两种情况下,唯一使用的内存由 JS 环境拥有,并受 JS 的垃圾收集器的约束。
GLib 对象是另一回事,因为它们是引用计数的,所以 JS 包装器对象可以简单地保存对它们的引用;当 JS 对象被 GC 时,它会释放它的引用,如果没有其他 JS 对象持有它,C 对象也会被销毁。