Haskell - FFI和指针

gua*_*aqe 4 haskell ffi

我正在使用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
Run Code Online (Sandbox Code Playgroud)

现在我遇到了必须能够使用该功能的问题.我看到的引用有类型BarPtr - > IO()的函数并且与之一起使用,它具有签名Storable a => a - >(Ptr a - > IO b) - > IO b,这是正常的,因为它们调用了主要功能.

但是,我想将这个函数包装在一个库中,得到一个没有IO的Bar - > Bar类型的函数,是否可以不使用unsafePerformIO?程序是什么?

Joh*_*n L 6

如果不使用,就无法IO从类型中删除unsafePerformIO.但是,在这种情况下,可以获得具有所需类型的函数,但需要注意一些注意事项.具体来说,C函数"foo"不能依赖于任何全局变量,线程局部状态或除单个参数之外的任何东西.此外,foo(bar)bar未更改时,调用应始终提供相同的结果.

我希望尝试导入C函数

bar foo(bar input);
Run Code Online (Sandbox Code Playgroud)

通过这个电话

f_foo :: BarPtr -> BarPtr
Run Code Online (Sandbox Code Playgroud)

由于结果类型,将导致编译器错误.我想你可能需要编写一个包装函数(在C中):

void wrap_foo(bar *barPtr) {
    bar outp = foo(*barPtr);
    *barPtr = outp;
}
Run Code Online (Sandbox Code Playgroud)

并将其导入为

f_wrap_foo :: BarPtr -> IO ()
Run Code Online (Sandbox Code Playgroud)

最后,您将调用此导入的函数:

fooBar :: Bar -> Bar
fooBar bar = unsafePerformIO $ with bar $ \barPtr -> do
    f_wrap_foo barPtr
    peek barPtr
Run Code Online (Sandbox Code Playgroud)