I find that the easiest way to understand what C2HS does is to look at the Haskell code it generates. In this case, the function hook
{#fun unsafe Initialized as ^ {alloca- `Bool' peekBool*} -> `()' discard*- #}
results in the following Haskell code (slightly tidied up):
initialized :: IO Bool
initialized =
alloca $ \a ->
initialized'_ a >>= \res ->
discard res >>
peekBool a
foreign import ccall unsafe "Control/Parallel/MPI/Internal.chs.h MPI_Initialized"
initialized'_ :: Ptr CInt -> IO CInt
Here, the "-
" following the marshaller for the input argument in the function hook means that that argument doesn't actually appear as an argument to the resulting Haskell function -- in this case what happens is that some space is allocated for the argument to MPI_Initialized
(using alloca
), the C function is called using a pointer to that allocated space, and the output of the Haskell function is returned using peekBool
to extract a value from the allocated space.
The type of the Haskell function that C2HS produces is just IO Bool
, i.e. the "input" parameter doesn't appear anywhere. (The C2HS documentation does kind of say this, but it's quite hard to interpret what it means until you've seen an example!)
The output marshaller just throws away the result of the call to the MPI_Initialized
C function, which is a status code that isn't very interesting in this case. The real return result from the Haskell code that C2HS produces is generated by the output marshaller for the pointer argument to the MPI_Initialized
function. The peekBool
function reads an integer value from a C int *
pointer and converts it to a Haskell Bool
; the "*
" in the output marshaller means that this value should be returned in the IO
monad.
This pattern of allocation with a "-
" as input marshaller, some sort of "peek" function with an "IO *
" as an output marshaller (and often discaring the C function's return value as well) is quite common. A lot of C libraries use this pattern of assigning results via pointers, and keeping track of pointer allocations by hand in Haskell is annoying, so C2HS tries to help with managing that for you. It takes a while to get used to where to put all the "-
"s and "*
"s, but looking at the Haskell code that C2HS generates is a really good way to understand what's going on.