我正在尝试将一些函数从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_ *函数创建的对象永远不会被垃圾回收。
是否有可能让格里布在水晶中与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*)
希望覆盖/重新定义g_malloc
和g_free
函数。
但它没有成功:它失败了分段错误。
如何使用GC制作滑稽的想法? 我发现了某种相关问题,但它对我没有帮助:Garbage collection with glib?
感谢advence。
答案 0 :(得分:1)
我建议将gobject-introspection用于此目的。它为每个库提供.GIR文件,该文件是一个大型XML文件,用于描述库中每个函数,类和方法的API,以及如何为每个输入和输出参数处理内存。您可以使用它为GLib等库动态生成绑定。
它还提供了一个扩展的单元测试库,您可以使用它来检查绑定是否正常工作。
至于内存管理,似乎要求覆盖g_malloc
和g_free
时遇到麻烦。它在JavaScript的gobject-introspection绑定中所做的等效方法是始终确保JS环境拥有内存。例如,对于从C函数返回的字符串;如果返回字符串的所有权被赋予调用者,则从返回的字符串(复制字符串)创建JS字符串,并释放返回的字符串。如果库保留了返回字符串的所有权,则会创建JS字符串,并且不会释放返回的字符串。在这两种情况下,使用的唯一内存都归JS环境所有,并受JS的垃圾收集器的限制。
GLib对象是另一个故事,因为它们是引用计数的,因此JS包装器对象可以简单地保存对它们的引用;当JS对象是GC时,它会释放它的引用,如果没有其他JS对象保留它,C对象也会被销毁。