I'm attempting to create a Haskell wrapper for a C library. The underlying structs are too complicated to express as explicit types, and I don't actually use them other than for passing between C functions, so I'm using EmptyDataDecls
to let GHC work it out for me.
What I need is a pointer to one of these data types, but when I attempt to create one with alloca
it complains that the data is not of the type Storable
. For example:
{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
module Main where
import Foreign.Marshal.Alloc
import Foreign.Ptr
data Struct
foreign import ccall "header.h get_struct"
get_struct :: Ptr Struct -> IO ()
main = alloca $ \ptr -> get_struct ptr
GHC won't compile this, saying there's no instance for Storable Struct
. I could implement it myself:
instance Storable Struct where
sizeOf _ = ...
alignment _ = ...
But that comes close to defeating the purpose - I don't want to have to define such things if I don't care what's in the struct.
I've noticed that a pointer to a pointer works fine, because the Ptr
class is Storable
. So I can accomplish what I'm aiming for by using peek
on ptr
before calling get_struct
:
main = alloca $ \ptr -> do
ptr <- peek ptr
get_struct ptr
This feels like a hack, though.
Is there a way to get empty data declarations to be considered Storable
without defining an instance?
You can't allocate something if you don't know how big it is. Is the function just going to ignore its argument? Then pass in a null pointer. Otherwise, you need to actually allocate enough space for the struct - don't cut corners by allocating a zero-byte or pointer-sized buffer, as then the called function will write past the end of your buffer, corrupting memory.
Either finish the data declaration, or write a Storable instance with proper size and alignment values; there's no way around providing size/alignment data in some form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With