6

我读过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 端访问它的元素?

4

2 回答 2

4

如果您不从 C 更改内存,则可以使用unsafeWith. 如果您确实需要从 C 进行更改,您可以先复制向量,或者在 C 端进行复制。(如果您确实需要从 C 中进行更改,但不再需要 Haskell 端的数据,您也可以unsafeWith在不复制的情况下使用,但是您必须确保不再使用向量。这可以狡猾,懒惰等等......)

那么,为什么不是when isVector a的实例呢?好吧,对于一个:向量应该是什么?回想一下,即使该函数具有 signature ,文档也说“未使用该参数”。希望知道内部情况的人能过来并给出权威的答案,但据我所知,所有实例都是“固定大小”类型。StorableasizeOf(Storable a) => a -> IntStorable

附录:您请求的函数签名实际上没有意义。假设你有一个foo :: Vector a -> Ptr (Vector a),那真的有意义foo (fromList [1,2]) == foo (init (fromList [1,2,3]))吗?请记住,这些现在是指针,并且很可能会有所不同。

于 2013-01-02T16:39:42.523 回答
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)
于 2013-10-31T16:07:30.097 回答