The `_ccall_' construct is part of the `IO' monad because 9 out of 10 uses will be to call imperative functions with side effects such as `printf'. Use of the monad ensures that these operations happen in a predictable order in spite of laziness and compiler optimisations.
To avoid having to be in the monad to call a C function, it is possible to use `unsafePerformIO', which is available from the `IOExts' module. There are three situations where one might like to call a C function from outside the IO world:
atan2d :: Double -> Double -> Double
atan2d y x = unsafePerformIO (_ccall_ atan2d y x)
sincosd :: Double -> (Double, Double)
sincosd x = unsafePerformIO $ do
da <- newDoubleArray (0, 1)
_casm_ "sincosd( %0, &((double *)%1[0]), &((double *)%1[1]) );" x da
s <- readDoubleArray da 0
c <- readDoubleArray da 1
return (s, c)
empty :: EFS x
update :: EFS x -> Int -> x -> EFS x
lookup :: EFS a -> Int -> a
empty = unsafePerformIO (_ccall_ emptyEFS)
update a i x = unsafePerformIO $
makeStablePtr x >>= \ stable_x ->
_ccall_ updateEFS a i stable_x
lookup a i = unsafePerformIO $
_ccall_ lookupEFS a i >>= \ stable_x ->
deRefStablePtr stable_x
You will almost always want to use `ForeignObj's with this.
trace :: String -> a -> a
trace string expr
= unsafePerformIO (
((_ccall_ PreTraceHook sTDERR{-msg-}):: IO ()) >>
fputs sTDERR string >>
((_ccall_ PostTraceHook sTDERR{-msg-}):: IO ()) >>
return expr )
where
sTDERR = ("stderr" :: Addr)
(This kind of use is not highly recommended -- it is only really
useful in debugging code.)