将glib绑定到Crystal语言中(GC问题)

5

我正在尝试将一些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*)

希望覆盖/重新定义g_mallocg_free函数,但是它不能正常工作:它会出现分段错误。
有什么想法可以让glib与GC一起使用吗? 我找到了一个相关的问题,但它没有帮助我:Garbage collection with glib? 提前感谢。

1
还可以查看https://github.com/jhass/crystal-gobject,它已经有了你似乎正在做的绑定。 - asterite
此外,在使用指针返回的指针后,请使用LibG.g_free(ptr)以避免内存泄漏。 - asterite
好的,谢谢!我还没有看过crystal-gobject项目。 - Sergey Potapov
1个回答

1
我建议使用gobject-introspection来实现这个目的。它为每个库提供一个.GIR文件,其中包含描述库中每个函数、类和方法的API的大型XML文件,以及如何处理每个输入和输出参数的内存。您可以使用它来动态生成像GLib这样的库的绑定。
它还提供了一个广泛的单元测试库,您可以使用它来检查您的绑定是否正常工作。
至于内存管理,覆盖g_malloc和g_free似乎是在寻求麻烦。在JavaScript的gobject-introspection绑定中,相当于始终确保JS环境拥有内存。例如,对于从C函数返回的字符串;如果将返回的字符串的所有权交给调用者,则会从返回的字符串创建一个JS字符串(复制字符串),并释放返回的字符串。如果库保留返回字符串的所有权,则创建一个JS字符串,而不释放返回字符串。在两种情况下,仅使用的内存归JS环境所有,并受JS的垃圾回收器控制。
GLib对象是另一种情况,因为它们是引用计数的,因此JS包装器对象可以简单地持有对它们的引用;当JS对象被GC'd时,它释放其引用,如果没有其他JS对象持有它,则C对象也将被销毁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接