Haskell Data.Vector.Storable.unsafeFromForeignPtr with field C struct pointer / array

I use Haskell FFI with the C library, which determines the number of types structcontaining elements that are pointers to doubles, intended to be processed as arrays of doubles:

typedef struct Foo {
  int length;
  double* values;
} FooT;

In my Haskell bindings to this library, I have an equivalent data type that I'm trying to use Data.Vector.Storable.Vector Doublefor an array:

data Foo = Foo {
  length :: Int,
  values :: Data.Vector.Storable.Vector Double
} deriving (Show, Eq)

To streamline the data between the C library and my Haskell code, I certainly have to write instances Storablefor these types. I am trying to develop a use case Data.Vector.Storable.unsafeFromForeignPtrfor creating Haskell Vectorfrom arrays double*that the C library allocated and populated on the heap. I hope that by doing this, I can avoid copying the contents of the arrays double*and just have Vectora kind of wrapper over the array. (A side question would be: given that arrays double*can be up to 10,000 doubles, is it worth chasing this not copying?)

This is what I still have. I use macros hsc2hsto generate an implementation 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)

, Storable ForeignPtr Double. , ForeignPtr Double, struct peek .

, (, ) struct , unsafeFromForeignPtr?

+4
2

hsc2hs, peek, . : , .

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  
+1

user2407038 newForeignPtr_, :

instance Storable Foo where
  alignment _ = alignment (undefined :: CDouble)
  sizeOf _ = #{size FooT}

  peek ptr = do
    len'    <- fmap fromIntegral (((#peek FooT, len) d) :: IO CInt)

    valuesField <- ((#peek FooT, values) ptr) :: IO (Ptr Double)
    valuesPtr   <- newForeignPtr_ valuesField
    let values' = DV.unsafeFromForeignPtr0 valuesField len

    return Foo { length = len, values = values' }

, #peek int , CInt, fromIntegral int . unsafeFromForeignPtr. double*: , Ptr Double.

struct char*, , int, , #peek. , CString .

0

Source: https://habr.com/ru/post/1543662/


All Articles