The module Foreign.Storable provides most elementary support for marshalling and is part of the language-independent portion of the Foreign Function Interface (FFI), and will normally be imported via the Foreign module.
The member functions of this class facilitate writing values of primitive types to raw memory (which may have been allocated with the above mentioned routines) and reading values from blocks of raw memory. The class, furthermore, includes support for computing the storage requirements and alignment restrictions of storable types.
Memory addresses are represented as values of type Ptr a, for some a which is an instance of class Storable. The type argument to Ptr helps provide some valuable type safety in FFI code (you can't mix pointers of different types without an explicit cast), while helping the Haskell type system figure out which marshalling method is needed for a given pointer.
All marshalling between Haskell and a foreign language ultimately boils down to translating Haskell data structures into the binary representation of a corresponding data structure of the foreign language and vice versa. To code this marshalling in Haskell, it is necessary to manipulate primitive data types stored in unstructured memory blocks. The class Storable facilitates this manipulation on all types for which it is instantiated, which are the standard basic types of Haskell, the fixed size Int types (Int8, Int16, Int32, Int64), the fixed size Word types (Word8, Word16, Word32, Word64), StablePtr, all types from Foreign.C.Types, as well as Ptr.
Minimal complete definition: sizeOf, alignment, one of peek, peekElemOff and peekByteOff, and one of poke, pokeElemOff and pokeByteOff.
A storable array is an IO-mutable array which stores its contents in a contiguous memory block living in the C heap. Elements are stored according to the class Storable. You can obtain the pointer to the array contents to manipulate elements from languages like C.
It is similar to IOUArray but slower. Its advantage is that it's compatible with C.
The module Data.Storable provides an extension to the Foreign.Storable type class adding support for variable-sized data types.
Provides a Storable instance for Complex which is binary compatible with C99, C++ and Fortran complex data types.
The only purpose of this package is to provide a standard location for this instance so that other packages needing this instance can play nicely together.
Storable instances with endianness
With this package you can build a Storable instance of a record type from Storable instances of its elements in an elegant way. It does not do any magic, just a bit arithmetic to compute the right offsets, that would be otherwise done manually or by a preprocessor like C2HS. I cannot promise that the generated memory layout is compatible with that of a corresponding C struct. However, the module generates the smallest layout that is possible with respect to the alignment of the record elements. If you encounter, that a record does not have a compatible layout, we should fix that. But also without C compatibility this package is useful e.g. in connection with StorableVector.
We provide Storable instance support for several cases:
* If you wrap a type in a newtype, then you can lift its Storable instance to that newtype with the module Foreign.Storable.Newtype. This way you do not need the GeneralizedNewtypeDeriving feature of GHC.
* If you have a type that is an instance of Traversable, you can use that feature for implementation of Storable methods. The module Foreign.Storable.Traversable allows manipulation of the portion of your type, that is accessible by Traversable methods. For instance with the type data T a = Cons Int [a] and an according Traversable implementation, you can load and store the elements of the contained list. This may be part of a Storable implementation of the whole type.
* If you have a record containing elements of various types, then you need module Foreign.Storable.Record.
Note however that the Storable instances defined with this package are quite slow in (up to) GHC-6.12.1. I'm afraid this is due to incomplete inlining, but we have still to investigate the problem.
For examples see packages storable-tuple and sample-frame.
Provides a Storable instance for pair and triple which should be binary compatible with C99 and C++. The only purpose of this package is to provide a standard location for this instance so that other packages needing this instance can play nicely together.
The array type
This package brings together the best of two worlds: The flexibility of plain lists and speed of low-level arrays. Lists are lazy per element, thus allowing for elegant tying-the-knot algorithms and correct fusion of subsequent operations, and they support any element type, including functions. Storablevectors do not have these features. Instead they are fast, including very fast access via indices, they are memory efficient and allow simple exchange with C.
This package provides the canonical functions for conversion from StorableVector to Stream and back. By a simple fusion rule they let the interim Stream based lists disappear in many situations, resulting in fast low-level loops. Such fusion could not be correct on StorableVectors. E.g. consider
> import qualified Data.StorableVector.Lazy as SV
> SV.zipWith f (SV.unfoldr size g a) (SV.cons b (SV.unfoldr size h c))
which yields a storable vector with the chunk structure
> [1, size, size, ...]
and the following strictness behaviour: For computation of the first value of the result, the first chunk with size size of SV.unfoldr size g a has to be fully evaluated. This has two advantages: Firstly, you do not really want that behaviour, but you accept it for the sake of overall performance. Secondly, the odd behaviour cannot easily be preserved by fusion, and we must resist to tell the optimizer incorrect rules.
So here is the solution: Write
> import qualified Data.StorableVector.Lazy.Stream as SVG
> import qualified Data.List.Stream as Stream
> SVG.from chunkSize $
> Stream.zipWith f
> (Stream.unfoldr g a)
> (Stream.cons b (Stream.unfoldr h c))
and get two advantages. First: You do not have to pass the size parameter at the leaves, but only once at the top. Second: Fusion jumps in and turns everything in a single efficient SV.unfoldr.
Automatically generates struct-rule based Storable instances based on the Generic typeclass.
Utilities useful for working with unioned data structures, where you want to use a different peek and poke. This is particularly useful for use with the ioctl package if you have an ioctl that provides output of a different type to the input.
Generic implementation of Storable
If you want to use it afterwards, ensure that you touchStorableArray after the last use of the pointer, so the array is not freed too early.
Construct a StorableArray from an arbitrary ForeignPtr. It is the caller's responsibility to ensure that the ForeignPtr points to an area of memory sufficient for the specified bounds.
The pointer to the array contents is obtained by withStorableArray. The idea is similar to ForeignPtr (used internally here). The pointer should be used only during execution of the IO action retured by the function passed as argument to withStorableArray.