castAny :: (Storable a, Storable b) => a -> b
castAny = unsafePerformIO . genericCast
where
genericCast :: (Storable a, Storable b) => a -> IO b
genericCast v = return undefined >>= \r ->
allocaBytes (max (sizeOf v) (sizeOf r)) $ \p ->
poke p v >> if False then return r else peek (castPtr p)
> let a = -1000 :: Int16
> castAny a :: Word16 -->
64536
> castAny a :: Ptr ()
0xb4c2fc18
Try it on a big endian architecture, or one that has alignment
restrictions, or a different size for HsChar or so forth. Casting by
'punning' (as the C folks like to call it) does have uses, but they are
generally hardware dependent and useful only in certain rare
circumstances that a generic cast probably isn't likely to fill.
Do you think this could be used as a way to handle
C unions? If I had something like
union example {
struct firstview {
char c;
int n;
} fv;
long double ld;
};
and 'firstview' had been mapped in Haskell as, say,
FirstView {firstViewC :: CChar, firstVewN :: CInt}
I could check what I would get after pokeing values
using:
(firstViewN . unionCast) (pi :: CDouble)
Note that I changed the name from castAny to unionCast
to reflect its use.
Thanks for your comments,
Maurício
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe