如何在 inline-c 中使用 Haskell 数组
How to work with Haskell Array in inline-c
向量有一个 Context
:vecCtx
允许从 C 代码访问 Haskell vector
。
我需要使用多维数组,所以 vector
不适合我。我更喜欢使用 array
。但是它没有 Context
。人们是否仍然可以以某种方式使用数组,或者他们是否为数组创建了一个特殊的上下文?
您可以像这样为 StorableArray
创建一个实例:
{-# 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
请注意,在这里使用 unsafePerformIO
是安全的,因为 getBounds
实际上是 StorableArray
下的纯函数。 array
包中没有不可变的可存储数组,所以你有点被它困在一个可变的世界里,考虑到你的目标是与 C 接口,这可能没问题。
话虽如此,我强烈建议您查看名为 massiv
的处理多维数组的库。如果您确实尝试过,这里是如何为 massiv 可存储可变和不可变数组创建 VecCtx
实例:
{-# 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
向量有一个 Context
:vecCtx
允许从 C 代码访问 Haskell vector
。
我需要使用多维数组,所以 vector
不适合我。我更喜欢使用 array
。但是它没有 Context
。人们是否仍然可以以某种方式使用数组,或者他们是否为数组创建了一个特殊的上下文?
您可以像这样为 StorableArray
创建一个实例:
{-# 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
请注意,在这里使用 unsafePerformIO
是安全的,因为 getBounds
实际上是 StorableArray
下的纯函数。 array
包中没有不可变的可存储数组,所以你有点被它困在一个可变的世界里,考虑到你的目标是与 C 接口,这可能没问题。
话虽如此,我强烈建议您查看名为 massiv
的处理多维数组的库。如果您确实尝试过,这里是如何为 massiv 可存储可变和不可变数组创建 VecCtx
实例:
{-# 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