Can the FFI deal with arrays? If so, how?
我很确定可以通过FFI发送数组,但是我找不到任何示例。例如,我有一个发送给
理想情况下,我想要最有效的方法-我不需要任何堆分配或不必要的复制。另外,如果我可以在Haskell和C中都使用Haskell的未装箱的数组,那将是很好的。那么这样做的方法是什么?
如果您使用Data.Vector库,则可以根据需要使用Data.Vector.Storable。然后,您可以使用unsafeToForeignPtr或unsafeWith之类的函数来访问基础外部指针。这使您可以调用C代码,而不会进行任何复制或封送处理。
如果要从C数组创建向量,可以使用unsafeFromForeignPtr。
您可以使用示例(假设c_foo不会修改其参数)
1 2 3 4 5 6 7 8 9 10 | 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) |
可以打到:
1 2 |
请注意,如果您的C函数修改了数据,则不应该这样做,而应该
制作数据副本以不破坏参照透明性。
如果要使用标准的Array-type,可以以相同的方式使用
FFI规范具有很高的可读性,因此您可能需要坐下来研究整个内容。但是,对于这个特定问题,您可以跳至"编组"部分,尤其是Ptr和Storable子部分,概述了可用于此目的的内容。
要将FFI Ptr转换为Haskell列表,可以使用:
http://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Foreign-Marshal-Array.html#v:peekArray0
与C语言一样,数组基本上是指向该数组的第一个成员的指针。您可以通过对指针进行算术来获取其他元素。