如何戳向量(或获取Ptr向量的数据)?

时间:2013-01-02 15:57:34

标签: haskell ffi

我已经读过Data.Vector.Storable将它的元素存储在连续的内存区域中。我一直期望VectorForeign.Storable的一个实例,或者至少会有一个函数:: Vector a -> Ptr (Vector a),但只有unsafeToForeignPtr0 :: Storable a => Vector a -> (ForeignPtr a, Int)

我的Haskell代码生成Foreign.Storable项的列表,我想从C代码访问此列表。 Vector.Storable正确的数据类型是否可以执行此操作,如果是,我应该如何从C端访问它的元素?

2 个答案:

答案 0 :(得分:4)

如果您没有从C更改内存,可以使用unsafeWith。如果确实需要从C进行更改,可以先复制矢量,或在C端复制。 (如果您确实需要从C进行更改,但不再需要Haskell端的数据,您也可以使用unsafeWith而无需复制,但是您必须确保该向量永远​​不会再次使用。这可能是棘手的,懒惰和所有......)

那么,为什么Vector a Storablea的实例不是(Storable a) => a -> Int?那么,对于一个:sizeOf对于一个向量应该是什么?回想一下,即使该函数具有签名Storable,文档也说“不使用该参数”。希望知道内部人员的人出现并提供权威答案,但据我所知,所有foo :: Vector a -> Ptr (Vector a)实例都是“固定大小”类型。

附录:您要求的功能签名无法真正理解。假设您有一个foo (fromList [1,2]) == foo (init (fromList [1,2,3])),{{1}}真的有意义吗?请记住,这些现在是指针,并且很可能是不同的。

答案 1 :(得分:1)

可能的解决方案:

import qualified Foreign.Ptr as P
import qualified Data.Vector.Storable as SV
import qualified Data.Vector.Storable.Internal as SVI
import qualified GHC.ForeignPtr as FP

ptr0ToVector :: SV.Storable a => P.Ptr a -> Int -> IO (SV.Vector a)
ptr0ToVector ptr size =
 FP.newForeignPtr_ ptr >>= \foreignPtr ->
 return (SV.unsafeFromForeignPtr0 foreignPtr size)

vectorToPtr0 :: SV.Storable a => SV.Vector a -> (P.Ptr a,Int)
vectorToPtr0 vector =
 let (foreignPtr,size) = SV.unsafeToForeignPtr0 vector
 in (SVI.getPtr foreignPtr,size)