Привязка 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_*, никогда не будут собираться мусором.
Можно ли заставить glib хорошо играть с Boehm GC в Crystal? Вдохновленный 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
функции. Но это не сработает: сбой с ошибкой сегментации.
Есть идеи, как заставить glib играть с GC? Я нашел какой-то связанный вопрос, но он мне не помог: сборка мусора с помощью glib?
Спасибо в адвенсе.
1 ответ
Я бы предложил использовать для этой цели gobject-introspection. Он предоставляет файл.GIR для каждой библиотеки, который представляет собой большой XML-файл, описывающий API каждой функции, класса и метода в библиотеке, а также порядок обработки памяти для каждого входного и выходного параметра. Вы можете использовать его для динамического создания привязок для библиотек, таких как GLib.
Он также предоставляет обширную библиотеку модульного тестирования, которую вы можете использовать для проверки правильности ваших привязок.
Что касается управления памятью, похоже, что просят проблемы переопределить g_malloc
а также g_free
, Эквивалентный способ, которым это делается в привязках gobject-introspection для JavaScript, состоит в том, чтобы всегда гарантировать, что среда JS владеет памятью. Например, для строк, возвращаемых из функции C; если право собственности на возвращенную строку передается вызывающей стороне, то из возвращенной строки (которая копирует строку) создается строка JS, и возвращаемая строка освобождается. Если библиотека сохраняет владение возвращенной строкой, то создается строка JS и возвращаемая строка не освобождается. В обоих случаях единственная используемая память принадлежит среде JS и зависит от сборщика мусора JS.
Объекты GLib - это другая история, так как они подсчитываются ссылками, и поэтому объект-обертка JS может просто содержать ссылку на них; когда объект JS является GC'd, он освобождает свою ссылку, и объект C также уничтожается, если никакой другой объект JS не удерживает его.