I'm using the Haskell FFI with a C library that defines a number of struct
types containing members which are pointers to double
s, intended to be treated as arrays of double
s:
typedef struct Foo {
int length;
double* values;
} FooT;
In my Haskell bindings to this library I have an equivalent data type in which I'm trying to use Data.Vector.Storable.Vector Double
for the array:
data Foo = Foo {
length :: Int,
values :: Data.Vector.Storable.Vector Double
} deriving (Show, Eq)
In order to marshall data between the C library and my Haskell code, of course, I have to write Storable
instances for these types. I'm trying to work out a way of using Data.Vector.Storable.unsafeFromForeignPtr
to create Haskell Vector
s from the double*
arrays that the C library has allocated and populated on the heap. I'm hoping that by doing this I can avoid copying the contents of the double*
arrays and just have the Vector
as a kind of wrapper over the array. (Side question would be: given that the double*
arrays can be up to 10,000s of double
s, is it worth pursuing this non-copying?)
This is what I have so far. I'm using hsc2hs
macros to help generate the Storable peek
implementation:
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)
So in my peek
I'm trying to #peek
the values
member as a ForeignPtr Double
which I could then use with unsafeFromForeignPtr
. However, #peek
generates code like this:
valuesField <- (((\ hsc_ptr -> peekByteOff hsc_ptr 16)) ptr) :: IO (ForeignPtr Double)
and gets stuck because there's no Storable
instance for ForeignPtr Double
. I think if I tried to implement an instance for ForeignPtr Double
I would just be commuting the problem of how to access the address value of a struct
member to the peek
implementation for that instance.
So in summary, how can I access an address value (i.e. pointer) struct
member in such a way that I can use it as an argument to unsafeFromForeignPtr
?