
quoth Evan Laforge
Anyway, in the big picture, I think hsc2hs is just too low level. We shouldn't be having to manually poke structs at all, and it's fundamentally dangerous even if you use all C types because there's no typechecking. Nothing will help you when someone updates the struct and forgets to update the Storable instance. If I were starting again (or advising someone who was starting from scratch), I'd try really hard to find something that directly generates marshalling code from the .h file, perhaps c2hs can do that.
I'm not up for generating anything directly from a .h file, but just for fun I put a little time today into an hsc alternative with a little more type safety. It works to a certain extent with integral types, because I can determine the size of the C field and assign an appropriate Haskell foreign integral type. I used it to generate a module for struct termios, for which I've been using hsc2hs, and it did better than hsc2hs in an unexpected way - hsc2hs #type maps "unsigned long" to "Word32", but on MacOS X the field size is 8 bytes. Then I make a raft of peek and poke functions that take the native Haskell values that you specify, and convert them to the appropriate foreign types. This is based on a descriptor file where you specify the fields you want to use, your Haskell name and type for each, and whether it's integral or whatever. Integral or whatever is where the joy leaks out of the concept, though. I'd bet a quarter that at least one in every four .hsc files contains some custom peeking and poking for a struct field, stuff you'd never anticipate. Full support for all types seems like a nearly unbounded problem. hsc2hs could do essentially what I'm talking about, if it could tell you the size of a field. Then you could declare the foreign types like termiosC_lflag :: (#appendfieldsize Word struct termios, c_lflag) which would expand to termiosC_lflag :: Word64 (fieldsize would be sizeof(x->c_lflag) * 8) This would give us foreign types based on the C declaration. You'd have to do the conversions yourself where you want to use native types, in this scenario. Donn