FFI可以处理数组吗? 如果是这样,怎么样?

我很确定可以通过FFI发送数组,但是我找不到任何示例。 例如,我有一个我发送给int foo(int*)函数的Haskell数组,或者我有一个C数组int bar[64]; 我发送给Haskell。

理想情况下,我想要最有效的方式 - 我不希望任何堆分配或不必要的复制。 另外,如果我可以在Haskell和C中使用Haskell的unboxed数组,那将会很好。那么这样做的方法是什么?


如果您使用Data.Vector库,则可以根据需要使用Data.Vector.Storable。 然后你可以使用诸如unsafeToForeignPtr或unsafeWith之类的函数来访问底层的外部指针。 这允许您在不进行任何复制或编组的情况下调用C代码。

如果你想从C数组创建一个向量,你可以使用unsafeFromForeignPtr。

你可以使用你的例子(假设c_foo不修改它的参数)

import Foreign.Ptr
import Foreign.C.Types
import System.IO.Unsafe (unsafePerformIO)
import qualified Data.Vector.Storable as SV

foreign import ccall unsafe "foo" c_foo :: Ptr CInt -> CInt

haskellFoo :: SV.Vector CInt -> CInt
haskellFoo sv = unsafePerformIO $
    SV.unsafeWith sv $ ptr -> return (c_foo ptr)

这可以打高尔夫球来:

haskellFoo sv = unsafePerformIO $
    SV.unsafeWith sv (return . c_foo)

请注意,如果您的C函数修改了数据,那么您不应该这样做,而应该制作一份数据副本以不破坏参考透明度。

如果你想使用标准的数组类型,你可以用同样的方式从Data.Array.Storable中使用withStorableArray


FFI规范非常易读,所以你可能只想坐下来解决整个问题。 但是,对于这个特定问题,您可以跳到“编组”部分,特别是Ptr和Storable子部分,它们概述了可用于此的部分。


要将FFI Ptr转换为Haskell列表,您可以使用:

peekArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO [a]

http://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Foreign-Marshal-Array.html#v%3ApeekArray0

链接地址: http://www.djcxy.com/p/61177.html

上一篇: Can the FFI deal with arrays? If so, how?

下一篇: Haskell FFI interlibrary dependencies