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