C-structs-0.1.0.1: README.md
# C-Structs in Haskell [](https://travis-ci.org/pinselimo/cstructs-in-haskell) [](https://matrix.hackage.haskell.org/package/C-structs) [](http://hackage.haskell.org/package/C-structs) [](https://hackage.haskell.org/package/C-structs)
C-structs lets you create dynamically typed and correctly padded C structs in Haskell.
These can be used for FFI calls, imports and exports.
This package is part of the development efforts for the Python library [```Pythas```](https://github.com/pinselimo/Pythas/).
Pythas provides an interface to import Haskell modules.
Note: As of GHC 8.10 structs cannot be passed by value, [only by reference](https://wiki.haskell.org/Foreign_Function_Interface#Foreign_types).
## Usage
You can use these types as a classic ```hackage``` package.
The library has no other dependencies than some of the ```Foreign.*``` modules contained in ```base```.
### Basics
~~~haskell
λ> import Foreign.C.Structs
λ> s = Struct2 1 2 :: Struct2 Int Int
~~~
can be interpreted as an equivalent to:
~~~C
struct Struct2 {
int s21st;
int s22nd;
};
struct Struct2 s;
s.s21st = 1;
s.s22nd = 2;
~~~
or with Python's ```ctypes```:
~~~python
>>> from ctypes import Structure, c_int
>>> class Struct2( Structure ):
... _fields_ = [("s21st", c_int), ("s22nd", c_int)]
...
>>> s = Struct2(1,2)
~~~
On memory all of these examples should have the exact same representation.
A pointer to either ```s``` can then be exchanged with the other and used in a ```foreign``` call.
### FFI usage
The following shows an example of a foreign import of a ```struct Struct2``` as defined above:
~~~C
struct Struct2 *foo (void) {
struct Struct2 *val;
val = malloc (sizeof (struct Struct2));
val->s21st = 42;
val->s22nd = 63;
return val;
}
~~~
can be imported in a Haskell module as follows:
~~~haskell
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.Ptr (Ptr)
import Foreign.Storable (peek)
import Foreign.Marshal.Alloc (free)
import Foreign.C.Types (CInt)
import Foreign.C.Structs (Struct2)
foreign import ccall "foo" foo :: Ptr (Struct2 CInt CInt)
main = do
putStrLn "Reading values from C.."
s <- peek foo
free foo
putStrLn "Received:"
putStrLn $ show s
~~~
For a more elaborated usage examples checkout [```Pythas```](https://github.com/pinselimo/Pythas) in conjunction with [```Pythas-Types```](https://github.com/pinselimo/Pythas-Types).
It uses ```Foreign.C.Structs``` to declare its storage functions for ```Haskell``` tuples. In addition, its Array and Linked List instances are based on this library.
### More fields
Currently ```C-structs``` exports types featuring up to six fields. If you require more, you can easily create them using Template Haskell and the ```structT``` function:
~~~haskell
structT 8
~~~
will create:
~~~haskell
data Struct8 = Struct8
{ s81st :: a
, s82nd :: b
, s83rd :: c
, s84th :: d
, s85th :: e
...
} deriving (Show, Eq)
instance Storable Struct8 ...
~~~
## Testing
Identity properties are tested with QuickCheck to ensure that peek and poke are reversible.
The result of ```sizeOf``` is dependent on the order of types. Its correctness can only be tested with HUnit.
The ```alignment``` function is trivial and only tested implicitly through ```sizeOf```.
Imports from C are tested in ```CTest.hs``` and together with the identity tests form the guarantee that also exports to C are consistent.
All tests are performed for all available GHC versions through [haskell-ci](https://github.com/haskell-CI/haskell-ci) to ensure maximum compatibility.
## License
This part of Pythas is licensed under the ```MIT``` License. Please be aware that the full ```Pythas``` package is under ```LGPLv3```. Refer to the accompanying LICENSE or COPYING files for details.