我已经读过Data.Vector.Storable将它的元素存储在连续的内存区域中。我一直期望Vector
是Foreign.Storable
的一个实例,或者至少会有一个函数:: Vector a -> Ptr (Vector a)
,但只有unsafeToForeignPtr0 :: Storable a => Vector a -> (ForeignPtr a, Int)
。
我的Haskell代码生成Foreign.Storable
项的列表,我想从C代码访问此列表。 Vector.Storable
正确的数据类型是否可以执行此操作,如果是,我应该如何从C端访问它的元素?
答案 0 :(得分:4)
如果您没有从C更改内存,可以使用unsafeWith
。如果确实需要从C进行更改,可以先复制矢量,或在C端复制。 (如果您确实需要从C进行更改,但不再需要Haskell端的数据,您也可以使用unsafeWith
而无需复制,但是您必须确保该向量永远不会再次使用。这可能是棘手的,懒惰和所有......)
那么,为什么Vector a
Storable
时a
的实例不是(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)