【发布时间】:2014-06-07 12:36:18
【问题描述】:
我正在使用带有 C 库的 Haskell FFI,该库定义了许多 struct 类型,其中包含指向 doubles 的成员,旨在被视为 doubles 的数组:
typedef struct Foo {
int length;
double* values;
} FooT;
在我与此库的 Haskell 绑定中,我有一个等效的数据类型,我正在尝试将 Data.Vector.Storable.Vector Double 用于数组:
data Foo = Foo {
length :: Int,
values :: Data.Vector.Storable.Vector Double
} deriving (Show, Eq)
为了在 C 库和我的 Haskell 代码之间编组数据,当然,我必须为这些类型编写 Storable 实例。我正在尝试找出一种使用Data.Vector.Storable.unsafeFromForeignPtr 从C 库已在堆上分配和填充的double* 数组创建Haskell Vectors 的方法。我希望通过这样做,我可以避免复制 double* 数组的内容,而只需将 Vector 作为数组的一种包装器。 (附带的问题是:鉴于double* 数组最多可以有10,000 个doubles,是否值得追求这种非复制?)
这是我目前所拥有的。我正在使用hsc2hs 宏来帮助生成Storable peek 实现:
instance Storable Foo where
alignment _ = alignment (undefined :: CDouble)
sizeOf _ = #{size FooT}
peek ptr = do
len <- (#peek FooT, length) ptr
valuesField <- ((#peek FooT, values) ptr) :: IO (ForeignPtr Double)
let values' = DV.unsafeFromForeignPtr0 valuesField len
return Foo { length = len, values = values' }
poke ptr (Foo len values') = do
(#poke FooT, length) ptr len
DV.unsafeWith values' (\ptrValues -> (#poke FooT, values) ptr ptrValues)
所以在我的peek 中,我尝试将#peek values 成员作为ForeignPtr Double 使用,然后我可以将其与unsafeFromForeignPtr 一起使用。但是,#peek 会生成如下代码:
valuesField <- (((\ hsc_ptr -> peekByteOff hsc_ptr 16)) ptr) :: IO (ForeignPtr Double)
因为没有ForeignPtr Double 的Storable 实例而被卡住。我想如果我尝试为ForeignPtr Double 实现一个实例,我只会将如何访问struct 成员的地址值的问题转换为该实例的peek 实现。
总之,我怎样才能访问地址值(即指针)struct 成员,以便我可以将其用作unsafeFromForeignPtr 的参数?
【问题讨论】:
标签: arrays pointers haskell vector ffi