bindings-common-0.1.2: src/Bindings/Utilities.hs
module Bindings.Utilities (
GlobalVariable, writeGlobalVariable, readGlobalVariable,
Callback(..)
) where
import Foreign
import Foreign.C
import Data.Int
-- | Haskell FFI imports global variables as pointers. To
-- ease manipulation of such pointers they are encapsulated
-- by 'GlobalVariable' so that values can be reached
-- directly, much like in an "Data.IORef".
newtype (Storable a) => GlobalVariable a = GlobalVariable (Ptr a)
writeGlobalVariable :: (Storable a) => GlobalVariable a -> a -> IO ()
writeGlobalVariable (GlobalVariable p) v = poke p v
readGlobalVariable :: (Storable a) => GlobalVariable a -> IO a
readGlobalVariable (GlobalVariable p) = peek p
-- | When libraries provide types for functions those
-- types are made instances of class 'Callback'. That
-- class is used to exchange between Haskell functions
-- and a representation (i.e., a hidden pointer) that
-- can be used or is provided by foreign code.
class (Storable cb) => Callback cb where
-- | The associated type is the function type
-- as it is used in Haskell.
type F cb :: *
-- | 'nullCallback' can be used like 'Foreign.Ptr.nullFunPtr'.
nullCallback :: cb
-- | 'makeCallback' takes a Haskell function and
-- gives a representation of it in the form of the
-- type expected by foreign code.
makeCallback :: F cb -> IO cb
-- | 'freeCallback' should be called on all values returned
-- by 'makeCallback' after they are no longer going to be
-- used. Most of the time this class method will just use
-- 'Foreign.Ptr.freeHaskellFunPtr'. of a foreign function
-- type after they are no longer going to be used.
freeCallback :: cb -> IO ()
-- | 'withCallback' just inserts an action between
-- calls to 'makeCallback' and 'freeCallback'.
-- Of course, it can't be used when foreign code
-- will save the function for latter use.
withCallback :: F cb -> (cb -> IO a) -> IO a
withCallback f c = do
made <- makeCallback f
result <- c made
freeCallback made
return result