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の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。しかし、うまくいきません: セグメンテーション違反で失敗します。

glib を GC でプレイする方法はありますか? どういうわけか関連する質問を見つけましたが、役に立ちませんでした:ガベージコレクションとglib?

よろしくお願いします。

4

1 に答える 1

1

この目的にはgobject-introspectionを使用することをお勧めします。これは、ライブラリ内の各関数、クラス、およびメソッドの API を記述する大きな XML ファイルである各ライブラリの .GIR ファイルと、各入力および出力パラメーターのメモリの処理方法を提供します。これを使用して、GLib などのライブラリのバインディングを動的に生成できます。

また、バインディングが正しく機能していることを確認するために使用できる広範な単体テスト ライブラリも提供します。

メモリ管理に関しては、オーバーライドg_mallocg_free. JavaScript の gobject-introspection バインディングで行われるのと同じ方法は、JS 環境がメモリを所有していることを常に確認することです。たとえば、C 関数から返される文字列の場合。返された文字列の所有権が呼び出し元に渡された場合、返された文字列から JS 文字列が作成され (文字列がコピーされます)、返された文字列は解放されます。ライブラリが返された文字列の所有権を保持している場合、JS 文字列が作成され、返された文字列は解放されません。どちらの場合も、使用中の唯一のメモリは JS 環境によって所有され、JS のガベージ コレクタの対象となります。

GLib オブジェクトは参照カウントされるため、別の話です。したがって、JS ラッパー オブジェクトは単純にそれらへの参照を保持できます。JS オブジェクトが GC されると、その参照が解放され、他の JS オブジェクトがそれを保持していなければ、C オブジェクトも同様に破棄されます。

于 2016-02-10T05:42:03.273 に答える