Begginer question about alignment in Storable

Hi, I need to make the following structure into an instance of Storable: struct { double w[2]; } Can I assume that its function 'alignment' should return the same as "alignment (1::CDouble)"? Or should it be "2 * alignment (1::CDouble)"? (I've read the wikipedia article about memory alignment, and what I understand is that there's a better alignment for hardware efficiency but compilers and programmers can do almost anything about it. What can I do when writing a library wrapper if I don't know what kind of compiler pragmas were used in all platforms that library was compiled?) Thanks, Maurício

Hello Maurício, Saturday, November 15, 2008, 11:29:23 PM, you wrote:
struct { double w[2]; }
Can I assume that its function 'alignment' should return the same as "alignment (1::CDouble)"? Or should it be "2 * alignment (1::CDouble)"?
secind - definitely not. first - probably yes -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

If you are using hsc2hs (if you are using Cabal this is easy; just
rename the file to *.hsc and Cabal will take care of the rest), then
there is a macro for making this easier and so you don't have to think
about it.
First, place the following at the top of your source file:
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t
(y__); }, y__)
Then #{alignment c_type} will always be expanded by hsc2hs to the
correct alignment for the C type named c_type.
On Sat, Nov 15, 2008 at 3:29 PM, Maurício
Hi,
I need to make the following structure into an instance of Storable:
struct { double w[2]; }
Can I assume that its function 'alignment' should return the same as "alignment (1::CDouble)"? Or should it be "2 * alignment (1::CDouble)"?
(I've read the wikipedia article about memory alignment, and what I understand is that there's a better alignment for hardware efficiency but compilers and programmers can do almost anything about it. What can I do when writing a library wrapper if I don't know what kind of compiler pragmas were used in all platforms that library was compiled?)
Thanks, Maurício
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

If you are using hsc2hs (if you are using Cabal this is easy; just rename the file to *.hsc and Cabal will take care of the rest), then there is a macro for making this easier and so you don't have to think about it. (...)
Well, after reading FFI addendum, I'm using my loyal text editor. Am I supposed to use something else? Is there something a tool like hsc2hs or cabal setup can do that is more portable than what I could write myself? Where should I learn about that? Thanks, Maurício

On Wed, Nov 19, 2008 at 1:01 PM, Mauricio
If you are using hsc2hs (if you are using Cabal this is easy; just rename the file to *.hsc and Cabal will take care of the rest), then there is a macro for making this easier and so you don't have to think about it. (...)
Well, after reading FFI addendum, I'm using my loyal text editor. Am I supposed to use something else? Is there something a tool like hsc2hs or cabal setup can do that is more portable than what I could write myself? Where should I learn about that?
Not necessarily more portable but definitely easier to maintain. The GHC manual contains [1] some sparse info on how to use hsc2hs (it seems to be built in to GHC). But the major advantage of hsc2hs is that if your C struct changes or you use a different C compiler, the allignment and size as well as the offsets used in peek and poke will still be correct since the compiler will calculate it for you. (Of course hsc2hs can't help you if fields are added or removed from the struct.) So for example suppose you had a struct like: typedef struct { int a; char b; double c; } my_struct; And you wanted to write a storable instance. With hsc2hs you would write it like this: instance Storable Struct where alignment _ = #{alignment my_struct} sizeOf _ = #{size my_struct} peek ptr = do a <- #{peek my_struct, a} ptr b <- #{peek my_struct, b} ptr c <- #{peek my_struct, c} ptr return (MyStruct a, b, c) poke ptr (MyStruct a b c) = do #{poke my_struct, a} ptr a #{poke my_struct, b} ptr b #{poke my_struct, c} ptr c Note that I didn't have to worry myself about what padding the compiler might put between for example "a" and "b" or what size "int" is. When I wrote the hpapi [2] package using hsc2hs was a life saver for these sorts of things. (You might look in those sources for examples.) Regarding "cabal setup", that is only really needed if you are intending to build a package to distribute to other people. But if you do want to distribute it (e.g. on the hackage repository) cabal is the way to go. I only mentioned it because if you are already using cabal then cabal automatically figures out that *.hsc files need to be sent through hsc2hs. (GHC may also do this, I haven't tried.) What this means is that once you spend the time to set up a cabal file for your project, the extra work for you as a developer to enable using hsc2hs is almost nothing; you just have to rename the file. For project structures that cabel can understand natively (e.g. you just have a colection of Haskell, Alex, Happy, Hsc2hs, etc. files), I highly recommend using it. It is one of the simplest to use build system I've seen. (I don't have a good link for learning cabal; you'll have to google around (e.g. "haskell cabal") for info.) Michael D. Adams [1] http://www.haskell.org/ghc/docs/latest/html/users_guide/hsc2hs.html [2] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hpapi

(...) But the major advantage of hsc2hs is that if your C struct changes or you use a different C compiler, the allignment and size as well as the offsets used in peek and poke will still be correct since the compiler will calculate it for you. (...)
And you wanted to write a storable instance. With hsc2hs you would write it like this: (...)
Thanks! This is actually a really nice tutorial! Do you mind if I try to find a place for it in the wiki?
Regarding "cabal setup", that is only really needed if you are intending to build a package to distribute to other people. (...)
I didn't know about hsc2hs, but I'm a big fan of cabal. I would use it even in "Hello Word".
(...) (I don't have a good link for learning cabal; you'll have to google around (e.g. "haskell cabal") for info.)
Compreensive as a reference, easy to follow as a tutorial: http://www.haskell.org/ghc/docs/latest/html/Cabal Best, Maurício

On Thu, Nov 20, 2008 at 11:26 AM, Mauricio
(...) But the major advantage of hsc2hs is that if your C struct changes or you use a different C compiler, the allignment and size as well as the offsets used in peek and poke will still be correct since the compiler will calculate it for you. (...)
And you wanted to write a storable instance. With hsc2hs you would write it like this: (...)
Thanks! This is actually a really nice tutorial! Do you mind if I try to find a place for it in the wiki?
Go right ahead(*). Of course if you put that in, you should note that the #{alignment foo} syntax is not currently built-in to hsc2hs. You have to add the following line to your haskell source file to add the alignment syntax: #let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) For completeness I should note that if you had a string field (e.g. struct { char c_string_field[MAX_LEN]; }) you would have to do it a little different. For example in peek: peek ptr = do s <- peekCString $ #{ptr c_type,c_string_field} ptr return (Foo s) Then in poke you would do: poke ptr (Foo s) = do withCStringLen (take maxLen value) $ uncurry (copyArray $ #{ptr c_type,c_string_field} ptr) where maxLen = #{const MAX_LEN} Note the use of #{ptr} instead of #{peek} since we want the address of the c_string_field rather than it's value. Unfortunately for the "struct { char *c_string_field; }" style there is no good general solution because you have to worry about allocating memory to have c_string_field point to. I'll leave figuring out #{enum}, but it can also be quite helpful in translating C enums/defines into Haskell. Michael D. Adams (*) For the lawyers: I hereby place that and these code snippet in the public domain or the nearest legal equivalent for those countries that don't have a legal concept of public domain.

Thanks! This is actually a really nice tutorial! Do you mind if I try to find a place for it in the wiki? Go right ahead (...)
For reference: http://haskell.org/haskellwiki/FFI_cook_book Best, Maurício
participants (4)
-
Bulat Ziganshin
-
Mauricio
-
Maurício
-
Michael D. Adams