5

一般情報

私は現在、C->Haskell (C2HS) Interface Generator for Haskell を試しています。一見しただけで、それは素晴らしかったです。かなり複雑な C++ ライブラリを (小さなextern C-wrapper を使用して) わずか 2 時間でインターフェイスしました。(そして、私は以前にFFIをしたことがありません。)

1 つだけ問題がありました。C/C++ ライブラリに割り当てられたメモリを解放するにはどうすればよいでしょうか。私{#pointer ... foreign #}C2HSのドキュメントで見つけましたが、それは私が求めているものとまったく同じように見えます. 私の C-wrapper は C++ ライブラリを機能的なインターフェースを備えた参照透過性を備えたライブラリに変換するので、Haskell Storage Manager は私のために大変な作業を行うことができるはずです :-)。残念ながら、私はこれを機能させることができませんでした。私の問題をよりよく説明するために、C/C++ ライブラリ + ラッパーと同じプロパティを持つがオーバーヘッドのない小さなデモ プロジェクトを GitHubにセットアップしました。ご覧のとおり、このライブラリはpure unsafeFFI で使用しても完全に安全です。

デモプロジェクト

GitHub で、次のような構成の小さなデモ プロジェクトを作成しました。

C ライブラリ

C ライブラリは非常に単純で役に立ちません: 整数を渡すことができ[0..n]、ライブラリから整数 (現在のところ) を返すことができます。覚えておいてください: ライブラリは役に立たず、ただのデモです。インターフェイスも非常に単純です。この関数LTIData lti_new_data(int n)は (整数を渡した後)、C ライブラリの割り当てられたデータを含むある種の不透明なオブジェクトを返します。ライブラリには 2 つのアクセサ関数int lti_element_count(LTIData data)ともint lti_get_element(LTIData data, int n)あり、前者は要素の数を返し、後者は要素を返しますn。ああ、最後になりましたが、ライブラリのユーザーは、ライブラリを使用した後、 を使用して不透明を解放する必要がありLTIDataますvoid lti_free_data(LTIData data)

低レベルの Haskell バインディング

低レベルの Haskell Binding は、C2HS を使用してセットアップされます。

高レベル Haskell API

また、お楽しみとして、低レベル API バインディングを使用する一種の高レベル Haskell APIと、高レベル API を使用する単純なドライバー プログラムもセットアップしました。ドライバ プログラムと valgrind などを使用すると、リークしたメモリを簡単に確認できます (p_1, p_2, ..., p_nライブラリが\sum_{i = 1..n} 1 + p_i割り当てを行うすべてのパラメータについて、以下のように簡単に確認できます)。

$ valgrind dist/build/TestHsLTI/TestHsLTI 100             2>&1 | grep -e allocs -e frees
==22647==   total heap usage: 184 allocs, 74 frees, 148,119 bytes allocated

$ valgrind dist/build/TestHsLTI/TestHsLTI 100 100         2>&1 | grep -e allocs -e frees
==22651==   total heap usage: 292 allocs, 80 frees, 181,799 bytes allocated

$ valgrind dist/build/TestHsLTI/TestHsLTI 100 100 100     2>&1 | grep -e allocs -e frees
==22655==   total heap usage: 400 allocs, 86 frees, 215,479 bytes allocated

$ valgrind dist/build/TestHsLTI/TestHsLTI 100 100 100 100 2>&1 | grep -e allocs -e frees
==22659==   total heap usage: 508 allocs, 92 frees, 249,159 bytes allocated

デモの現状

次のように入力するだけで、プロジェクトを複製、コンパイル、実行できるはずです。git clone https://github.com/weissi/c2hs-experiments.git && cd c2hs-experiments && cabal configure && cabal build && dist/build/TestHsLTI/TestHsLTI

では、問題は何ですか?

問題は、プロジェクトがC2HS を使用Foreign.Ptrする「管理された」バージョンのみを使用し、それを機能させることができないことです。デモ プロジェクトでは、これらの外部ポインタを使用しようとするファイルも追加しましたが、機能しません :-(。一生懸命試しましたが、成功しませんでした。Foreign.ForeignPtr{#pointer ... foreign #}.chs

また、私が理解できないことが 1 つあります。それは、C2HS を使用して GHC にライブラリのデータを解放する方法を伝える方法です。デモ プロジェクトのライブラリにはvoid lti_free_data(LTIData data)、メモリを解放するために呼び出される関数が用意されています。しかし、GHCはそれを推測することはできません!?! GHC が通常の a を使用する場合free()、すべてのメモリが解放されるわけではありません :-(.

4

1 に答える 1

3

問題解決:このファイルがインターネット上で同様のことをしているのを見つけ、解決できました :-)。

必要なのは、いくつかのボイラープレート マーシャリング コードだけでした。

foreign import ccall "lib_to_interface.h &lti_free_data"
  ltiFreeDataPtr :: FunPtr (Ptr (LTIDataHs) -> IO ())


newObjectHandle :: Ptr LTIDataHs -> IO LTIDataHs
newObjectHandle p = do
  fp <- newForeignPtr ltiFreeDataPtr p
  return $ LTIDataHs fp

ファイルの管理された ( ForeignPtr) バージョンの.chs最終版は次のとおりです。

于 2012-08-22T11:10:31.777 に答える