I've read that Data.Vector.Storable stores it's elements in a consecutive memory region. I've been expecting that Vector
would be an instance of Foreign.Storable
or at least there would be a function :: Vector a -> Ptr (Vector a)
, but there is only unsafeToForeignPtr0 :: Storable a => Vector a -> (ForeignPtr a, Int)
.
My Haskell code produces a list of Foreign.Storable
things and i want access this list from the C code. Is Vector.Storable
right data type to do this, and if yes - how should i access it's elements from the C side?
If you're not changing the memory from C, you can use unsafeWith
. If you do need to make changes from C, you can copy the vector first, or make a copy on the C side. (In case you do need to make changes from C, but don't need the data on the Haskell side any more, you can also use unsafeWith
without copying, but then you have to make sure that the vector is never again used. This can be tricky, with laziness and all...)
So, why isn't Vector a
an instance of Storable
when a
is? Well, for one: what should sizeOf
be for a vector? Recall that even though that function has signature (Storable a) => a -> Int
, the documentation says "the argument is not used". Hopefully someone who knows the internals comes around and gives an authoritative answer, but as far as I know, all the Storable
instances are "fixed-size" types.
Addendum: The function signatures you're requesting can't really make sense. Suppose you had a foo :: Vector a -> Ptr (Vector a)
, would it really make sense that foo (fromList [1,2]) == foo (init (fromList [1,2,3]))
? Remember, these are now pointers, and could very well be different.
A possible solution:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With