There's a Context
for vectors: vecCtx
which allows access to Haskell vector
from C code.
I need to work with multi-dimentional arrays so vector
doesn't cut for me. I prefer to use array
. But there isn't a Context
for it. Do people somehow can still work with arrays or do they create a special context for arrays?
CodePudding user response:
You can create an instance for a StorableArray
like so:
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Array where
import Data.Array.Storable
import Foreign.Storable (Storable)
import Language.C.Inline.Context
import System.IO.Unsafe (unsafePerformIO)
instance (Ix ix, Storable e) => VecCtx (StorableArray ix e) where
type VecCtxScalar (StorableArray ix e) = e
vecCtxLength = rangeSize . unsafePerformIO . getBounds
vecCtxUnsafeWith = withStorableArray
Note that it is safe to use unsafePerformIO
here because getBounds
is really a pure function underneath for StorableArray
. There is no immutable storable array in array
package, so you are sort of stuck in a mutable world with it, which might be fine, considering that your goal is to interface with C.
That being said, I highly recommend checking out library for dealing with multi-dimensional arrays that's called massiv
. In case you do give it a try, here is how to create VecCtx
instance for massiv storable mutable and immutable arrays:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Massiv where
import Data.Massiv.Array
import Data.Massiv.Array.Unsafe (unsafeWithPtr)
import Language.C.Inline.Context
instance (Index ix, Storable e) => VecCtx (Array S ix e) where
type VecCtxScalar (Array S ix e) = e
vecCtxLength = totalElem . size
vecCtxUnsafeWith = unsafeWithPtr
instance (Index ix, Storable e) => VecCtx (MArray RealWorld S ix e) where
type VecCtxScalar (MArray RealWorld S ix e) = e
vecCtxLength = totalElem . sizeOfMArray
vecCtxUnsafeWith = withPtr