垃圾收集 – 将glib绑定到Crystal lang(GC问题)

我试图将一些函数从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可以使glib发挥得更好吗?灵感来自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函数.
但它没有成功:它失败了分段错误.

任何想法如何使用gl?
我发现了一些相关的问题,但它没有帮助我:Garbage collection with glib?

谢谢你的到来.

最佳答案 我建议将
gobject-introspection用于此目的.它为每个库提供.GIR文件,该文件是一个大型XML文件,用于描述库中每个函数,类和方法的API,以及如何为每个输入和输出参数处理内存.您可以使用它为GLib等库动态生成绑定.

它还提供了一个扩展的单元测试库,您可以使用它来检查绑定是否正常工作.

至于内存管理,似乎要求覆盖g_malloc和g_free的麻烦.它在JavaScript的gobject-introspection绑定中所做的等效方法是始终确保JS环境拥有内存.例如,对于从C函数返回的字符串;如果返回字符串的所有权被赋予调用者,则从返回的字符串(复制字符串)创建JS字符串,并释放返回的字符串.如果库保留了返回字符串的所有权,则会创建JS字符串,并且不会释放返回的字符串.在这两种情况下,使用的唯一内存由JS环境拥有,并受JS的垃圾收集器限制.

GLib对象是另一个故事,因为它们是引用计数的,因此JS包装器对象可以简单地保存对它们的引用;当JS对象是GC’d时,它会释放它的引用,如果没有其他JS对象持有它,C对象也会被销毁.

点赞