我正在使用FFI以便在C中使用一个带有结构并返回相同结构的函数。我看到的引用说我必须使用指向这些结构的指针才能将它导入Haskell。所以,例如。
data Bar = Bar { a :: Int, b :: Int }
type BarPtr = Ptr (Bar)
foreign import ccall "static foo.h foo"
f_foo :: BarPtr -> BarPtr
现在我遇到了必须能够使用该功能的问题。我看到references的函数类型为 BarPtr - > IO()并使用 with ,其签名为 Storable a => a - > (Ptr a - > IO b) - > IO b ,这很好,因为他们在main中调用函数。
但是,我想将此函数包装在库中,获取类型为 Bar - >的函数。栏没有IO,是否可以不使用 unsafePerformIO ?程序是什么?
答案 0 :(得分:5)
如果不使用IO
,则无法从类型中删除unsafePerformIO
。但是,在这种情况下,可以获得具有所需类型的函数,但需要注意一些注意事项。具体来说,C函数“foo”不能依赖于任何全局变量,线程局部状态或除单个参数之外的任何东西。此外,当foo(bar)
未更改时,调用bar
应始终提供相同的结果。
我希望尝试导入C函数
bar foo(bar input);
通过此次通话
f_foo :: BarPtr -> BarPtr
由于结果类型,将导致编译器错误。我想你可能需要编写一个包装函数(在C中):
void wrap_foo(bar *barPtr) {
bar outp = foo(*barPtr);
*barPtr = outp;
}
并将其导入为
f_wrap_foo :: BarPtr -> IO ()
最后,您可以使用以下命令调用此导入的函数:
fooBar :: Bar -> Bar
fooBar bar = unsafePerformIO $ with bar $ \barPtr -> do
f_wrap_foo barPtr
peek barPtr