尝试将ForeignPtr参数用于动态包装器

时间:2016-02-07 10:35:02

标签: haskell ffi c2hs

我正在尝试使用c2hs包装C库。我有一个不透明的C结构,我在Haskell中映射如下:

{#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指针,但我不知道如何做到/将它放在“包装器”中。

任何线索?

1 个答案:

答案 0 :(得分: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