将 glib 绑定​​到 Crystal lang(GC 问题)

Ser*_*pov 5 garbage-collection glib boehm-gc crystal-lang

我正在尝试将一些函数从 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
Run Code Online (Sandbox Code Playgroud)

然而它引入了内存泄漏:使用 g_* 函数创建的对象永远不会被垃圾收集。

是否有可能让glib在Crystal中与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*)
Run Code Online (Sandbox Code Playgroud)

希望覆盖/重新定义g_mallocg_free功能。但它不起作用:它因分段错误而失败。

有什么想法可以让 glib 与 GC 一起玩吗?我发现了某种相关的问题,但它对我没有帮助:Garbage collection with glib?

提前致谢。

pto*_*ato 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 对象也会被销毁。