module NHC.FFI ( -- combined allocation and marshalling with, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b new, -- :: Storable a => a -> IO (Ptr a) -- marshalling of Boolean values (non-zero corresponds to `True') fromBool, -- :: Num a => Bool -> a toBool, -- :: Num a => a -> Bool -- marshalling of Maybe values maybeNew, -- :: ( a -> IO (Ptr a)) -- -> (Maybe a -> IO (Ptr a)) maybeWith, -- :: ( a -> (Ptr b -> IO c) -> IO c) -- -> (Maybe a -> (Ptr b -> IO c) -> IO c) maybePeek, -- :: (Ptr a -> IO b ) -- -> (Ptr a -> IO (Maybe b)) -- marshalling lists of storable objects withMany, -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res -- Haskellish interface to memcpy and memmove -- (argument order: destination, source) copyBytes, -- :: Ptr a -> Ptr a -> Int -> IO () moveBytes -- :: Ptr a -> Ptr a -> Int -> IO () ) where import Ptr import Storable import MarshalAlloc import CTypes import CTypesExtra -- combined allocation and marshalling -- ----------------------------------- -- allocate storage for a value and marshal it into this storage -- new :: Storable a => a -> IO (Ptr a) new val = do ptr <- malloc poke ptr val return ptr -- allocate temporary storage for a value and marshal it into this storage -- -- * see the life time constraints imposed by `alloca' -- with :: Storable a => a -> (Ptr a -> IO b) -> IO b with val f = alloca $ \ptr -> do poke ptr val res <- f ptr destruct ptr return res -- marshalling of Boolean values (non-zero corresponds to `True') -- ----------------------------- -- convert a Haskell Boolean to its numeric representation -- fromBool :: Num a => Bool -> a fromBool False = 0 fromBool True = 1 -- convert a Boolean in numeric representation to a Haskell value -- toBool :: Num a => a -> Bool toBool = (/= 0) -- marshalling of Maybe values -- --------------------------- -- allocate storage and marshall a storable value wrapped into a `Maybe' -- -- * the `nullPtr' is used to represent `Nothing' -- maybeNew :: ( a -> IO (Ptr a)) -> (Maybe a -> IO (Ptr a)) maybeNew = maybe (return nullPtr) -- converts a withXXX combinator into one marshalling a value wrapped into a -- `Maybe' -- maybeWith :: ( a -> (Ptr b -> IO c) -> IO c) -> (Maybe a -> (Ptr b -> IO c) -> IO c) maybeWith = maybe ($ nullPtr) -- convert a peek combinator into a one returning `Nothing' if applied to a -- `nullPtr' -- maybePeek :: (Ptr a -> IO b) -> Ptr a -> IO (Maybe b) maybePeek peek ptr | ptr == nullPtr = return Nothing | otherwise = do a <- peek ptr; return (Just a) -- marshalling lists of storable objects -- ------------------------------------- -- replicates a withXXX combinator over a list of objects, yielding a list of -- marshalled objects -- withMany :: (a -> (b -> res) -> res) -- withXXX combinator for one object -> [a] -- storable objects -> ([b] -> res) -- action on list of marshalled obj.s -> res withMany _ [] f = f [] withMany withFoo (x:xs) f = withFoo x $ \x' -> withMany withFoo xs (\xs' -> f (x':xs')) -- Haskellish interface to memcpy and memmove -- ------------------------------------------ -- copies the given number of bytes from the second area (source) into the -- first (destination); the copied areas may *not* overlap -- copyBytes :: Ptr a -> Ptr a -> Int -> IO () copyBytes dest src size = _memcpy dest src (fromIntegral size) >> return () -- copies the given number of elements from the second area (source) into the -- first (destination); the copied areas *may* overlap -- moveBytes :: Ptr a -> Ptr a -> Int -> IO () moveBytes dest src size = _memmove dest src (fromIntegral size) >> return () -- auxiliary routines -- ------------------- -- basic C routines needed for memory copying -- foreign import noproto "memcpy" _memcpy :: Ptr a -> Ptr a -> CSize -> IO (Ptr a) foreign import noproto "memmove" _memmove :: Ptr a -> Ptr a -> CSize -> IO (Ptr a)