加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

数组 – 带有C struct指针/数组字段的Haskell Data.Vector.Stora

发布时间:2020-12-16 07:09:00 所属栏目:百科 来源:网络整理
导读:我正在使用带有C库的 Haskell FFI,它定义了许多结构类型,这些结构类型包含指向双精度的成员,旨在被视为双精度数组: typedef struct Foo { int length; double* values;} FooT; 在我对这个库的Haskell绑定中,我有一个等效的数据类型,我正在尝试使用Data.Vect
我正在使用带有C库的 Haskell FFI,它定义了许多结构类型,这些结构类型包含指向双精度的成员,旨在被视为双精度数组:

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代码之间编组数据,我必须为这些类型编写可存储的实例.我正在尝试使用Data.Vector.Storable.unsafeFromForeignPtr来从C库已分配并填充在堆上的double *数组创建Haskell Vectors.我希望通过这样做我可以避免复制double *数组的内容,只需将Vector作为数组的一种包装器. (旁边的问题是:假设双*阵列可以达到10,000s的双倍,是否值得追求这种非复制?)

这就是我到目前为止所拥有的.我正在使用hsc2hs宏来帮助生成可存储的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作为ForeignPtr Double,然后我可以将其与unsafeFromForeignPtr一起使用.但是,#peek会生成如下代码:

valuesField <- ((( hsc_ptr -> peekByteOff hsc_ptr 16)) ptr) :: IO (ForeignPtr Double)

因为ForeignPtr Double没有可存储的实例而被卡住了.我想如果我试图为ForeignPtr Double实现一个实例,我只是将如何访问struct成员的地址值的问题转换为该实例的peek实现.

总而言之,如何以这样的方式访问地址值(即指针)struct成员,以便将其用作unsafeFromForeignPtr的参数?

解决方法

我不知道如何使用hsc2hs,但你已经有了一个指向数据的指针,所以你只需要使用它,当然要有适当的偏移量.免责声明:此编译,但未经测试.

import Data.Vector.Storable (Vector,unsafeFromForeignPtr)
import Foreign.Storable (Storable (..))
import Foreign.C.Types 
import Foreign.ForeignPtr (newForeignPtr_)
import Foreign.Ptr 

instance Storable Foo where
  peek ptr = do 
    len <- peek (castPtr ptr)
    valsPtr <- newForeignPtr_  (castPtr ptr `plusPtr` (sizeOf (undefined :: CInt)))
    return $Foo len $unsafeFromForeignPtr valsPtr 0 len

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读