如何在 inline-c 中使用 Haskell 数组

How to work with Haskell Array in inline-c

向量有一个 ContextvecCtx 允许从 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