2

c2hs を使用して C ライブラリをラップしようとしています。次のように Haskell でマッピングした不透明な C 構造体があります。

{#pointer *foo as Foo foreign newtype #}

ファイナライザーで自動的にクリーンアップできるように、外部ポインターを使用しました。それはすべてうまくいくようです。ただし、次のような関数ポインターをラップしたいと思います。

typedef void (*hook_func)(foo *f, int a);

私の Haskell コードは次のようになります。

type HookFunc = Foo -> Int -> IO ()
foreign import ccall "wrapper"
    mkHookFunc :: HookFunc -> IO (FunPtr HookFunc)

ただし、コンパイルすると、次のエラーが発生します。

Unacceptable argument type in foreign declaration:
    ForeignPtr Foo

このエラーの最善の解決策についてのアイデアはありますか? 私の最初の考えは、unsafeForeignPtrToPtr単に foo ポインターに変換するために使用する必要があるということですが、これを行う方法や「ラッパー」に配置する場所がわかりません。

手がかりはありますか?

4

1 に答える 1

1

整理できたと思います。

gtk2hs で、私が望んでいたものと似たようなコードを見つけました ( https://github.com/gtk2hs/gtk2hs/blob/master/gio/System/GIO/Async/AsyncResult.chs )

コールバックを通常どおりに定義しました。

type HookFunc = Foo -> Int -> IO ()

次に、 の型を使用する別の型も定義しましたForeign.C

type CHookFunc = Foo -> CInt -> IO ()

ラッパーは次のようになりました。

foreign import "wrapper"
    mkHookFunc :: CHookFunc -> IO {# type hook_func_t #} -- hook_func_t is the typedef in the C header file

最後に、次のようにマーシャリング関数を追加しました。

marshalHookFunc :: HookFunc -> IO {# type hook_func_t #}
marshalHookFunc hookFunc =
    mkHookFunc $ \fooPtr i -> do
        foo <- mkFoo fooPtr -- mkFoo constructs a ForeignPtr Foo out of a Ptr Foo
        hookFunc foo i
于 2016-02-13T03:35:46.950 に答える