Marshalling C unions

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Marshalling C unions

Nabil Alsharif
Hi everybody,

I know this sounds like an issue many have faced before me, but good old
google didn't come up with any helpful results. The basic problem is
that I need to marshal a union so I can pass it to a C function via FFI.
So to make sure I have my head wrapped around this correctly, say I have
a union like so:
typedef union {
     int i;
     char c;
} my_union;

This would typically be represented in Haskell as:
data myUnion = I CInt | C CChar

My question is how would you marshall (define an Storable instance for)
myUnion into my_union? It's my understanding that an instance my_union
would take up sizeof(int) bytes in memory, i.e. the size of it's largest
member. So to store this we would write something along the lines of:
instance Storable myUnion where
     size _ = #{size my_union} -- <-- hsc2hs shortcut
     alignment _ = alignment undefined::CInt -- <-- What should this
really be?
     peek ptr = do -- <-- How are you supposed to know which element to
extract?
     poke ptr (I i) =  poke ptr i -- <-- Or should this be #{poke
my_union, i} ptr i ?
     poke ptr (C c) = poke ptr c

I hope this clear. I appreciate all the help. If this question has
already been answered, which I'm sure it has, please point me to right
spot. Thanks again for everyone's time.

Nabil Alsharif.

_______________________________________________
FFI mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/ffi
Reply | Threaded
Open this post in threaded view
|

Re: Marshalling C unions

Henning Thielemann

On Wed, 13 Apr 2011, Nabil Alsharif wrote:

> instance Storable myUnion where
>    size _ = #{size my_union} -- <-- hsc2hs shortcut
>    alignment _ = alignment undefined::CInt -- <-- What should this really
> be?
>    peek ptr = do -- <-- How are you supposed to know which element to extract?

That's the great "feature" of C unions, that you cannot know that in
general. You have to store somewhere else, in a boolean or flag set,
whether the stored union value contains a 'char' or an 'int'.

>    poke ptr (I i) =  poke ptr i -- <-- Or should this be #{poke my_union, i}  ptr i ?
>    poke ptr (C c) = poke ptr c

_______________________________________________
FFI mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/ffi