-- Stability : provisional
-- Portability : portable
--
--- This module defines foreign pointers, i.e. addresses with associated
--- finalizers.
+-- The 'ForeignPtr' type and operations. This module is part of the
+-- Foreign Function Interface (FFI) and will usually be imported via
+-- the "Foreign" module.
--
-----------------------------------------------------------------------------
module Foreign.ForeignPtr
- ( ForeignPtr, -- abstract, instance of: Eq
+ (
+ -- * Finalised data pointers
+ ForeignPtr, -- abstract, instance of: Eq
, newForeignPtr -- :: Ptr a -> IO () -> IO (ForeignPtr a)
, addForeignPtrFinalizer -- :: ForeignPtr a -> IO () -> IO ()
, withForeignPtr -- :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")
#ifdef __GLASGOW_HASKELL__
+-- |The type 'ForeignPtr' represents references to objects that are
+-- maintained in a foreign language, i.e., that are not part of the
+-- data structures usually managed by the Haskell storage manager.
+-- The essential difference between 'ForeignPtr's and vanilla memory
+-- references of type @Ptr a@ is that the former may be associated
+-- with /finalisers/. A finaliser is a routine that is invoked when
+-- the Haskell storage manager detects that - within the Haskell heap
+-- and stack - there are no more references left that are pointing to
+-- the 'ForeignPtr'. Typically, the finaliser will, then, invoke
+-- routines in the foreign language that free the resources bound by
+-- the foreign object.
+--
+-- The 'ForeignPtr' is parameterised in the same way as 'Ptr'. The
+-- type argument of 'ForeignPtr' should normally be an instance of
+-- class 'Storable'.
+--
data ForeignPtr a = ForeignPtr ForeignObj#
+
instance CCallable (ForeignPtr a)
eqForeignPtr :: ForeignPtr a -> ForeignPtr a -> Bool
p /= q = not (eqForeignPtr p q)
newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
+-- ^Turns a plain memory reference into a foreign object
+-- by associating a finaliser - given by the monadic operation
+-- - with the reference. The finaliser will be executed after
+-- the last reference to the foreign object is dropped. Note
+-- that there is no guarantee on how soon the finaliser is
+-- executed after the last reference was dropped; this depends
+-- on the details of the Haskell storage manager. The only
+-- guarantee is that the finaliser runs before the program
+-- terminates.
newForeignPtr p finalizer
= do fObj <- mkForeignPtr p
addForeignPtrFinalizer fObj finalizer
return fObj
addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO ()
+-- ^This function adds another finaliser to the given
+-- foreign object. No guarantees are made on the order in
+-- which multiple finalisers for a single object are run.
addForeignPtrFinalizer (ForeignPtr fo) finalizer =
IO $ \s -> case mkWeak# fo () finalizer s of { (# s1, w #) -> (# s1, () #) }
(# s1#, fo# #) -> (# s1#, ForeignPtr fo# #) )
touchForeignPtr :: ForeignPtr a -> IO ()
+-- ^This function ensures that the foreign object in
+-- question is alive at the given place in the sequence of IO
+-- actions. In particular 'withForeignPtr'
+-- does a 'touchForeignPtr' after it
+-- executes the user action.
+--
+-- This function can be used to express liveness
+-- dependencies between 'ForeignPtr's: for
+-- example, if the finalizer for one
+-- 'ForeignPtr' touches a second
+-- 'ForeignPtr', then it is ensured that the
+-- second 'ForeignPtr' will stay alive at
+-- least as long as the first. This can be useful when you
+-- want to manipulate /interior pointers/ to
+-- a foreign structure: you can use
+-- 'touchForeignObj' to express the
+-- requirement that the exterior pointer must not be finalized
+-- until the interior pointer is no longer referenced.
touchForeignPtr (ForeignPtr fo)
= IO $ \s -> case touch# fo s of s -> (# s, () #)
withForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+-- ^This is a way to look at the pointer living inside a
+-- foreign object. This function takes a function which is
+-- applied to that pointer. The resulting 'IO' action is then
+-- executed. The foreign object is kept alive at least during
+-- the whole action, even if it is not used directly
+-- inside. Note that it is not safe to return the pointer from
+-- the action and use it after the action completes. All uses
+-- of the pointer should be inside the
+-- 'withForeignPtr' bracket. The reason for
+-- this unsafety is the same as for
+-- 'foreignPtrToPtr' below: the finalizer
+-- may run earlier than expected, because the compiler can only
+-- track usage of the 'ForeignPtr' object, not
+-- a 'Ptr' object made from it.
+--
+-- This function is normally used for marshalling data to
+-- or from the object pointed to by the
+-- 'ForeignPtr', using the operations from the
+-- 'Storable' class.
withForeignPtr fo io
= do r <- io (foreignPtrToPtr fo)
touchForeignPtr fo
return r
foreignPtrToPtr :: ForeignPtr a -> Ptr a
+-- ^This function extracts the pointer component of a foreign
+-- pointer. This is a potentially dangerous operations, as if the
+-- argument to 'foreignPtrToPtr' is the last usage
+-- occurence of the given foreign pointer, then its finaliser(s) will
+-- be run, which potentially invalidates the plain pointer just
+-- obtained. Hence, 'touchForeignPtr' must be used
+-- wherever it has to be guaranteed that the pointer lives on - i.e.,
+-- has another usage occurrence.
+--
+-- To avoid subtle coding errors, hand written marshalling code
+-- should preferably use 'withForeignPtr' rather
+-- than combinations of 'foreignPtrToPtr' and
+-- 'touchForeignPtr'. However, the later routines
+-- are occasionally preferred in tool generated marshalling code.
foreignPtrToPtr (ForeignPtr fo) = Ptr (foreignObjToAddr# fo)
+castForeignPtr :: ForeignPtr a -> ForeignPtr b
+-- ^This function casts a 'ForeignPtr'
+-- parameterised by one type into another type.
castForeignPtr (ForeignPtr a) = ForeignPtr a
#endif
-----------------------------------------------------------------------------
module Foreign.Marshal.Alloc (
+ -- * Allocation
malloc, -- :: Storable a => IO (Ptr a)
mallocBytes, -- :: Int -> IO (Ptr a)
-- exported functions
-- ------------------
--- allocate space for storable type
+-- |Allocate space for storable type. The size of the area allocated
+-- is determined by the 'sizeOf' method from the instance of
+-- 'Storable' for the appropriate type.
--
malloc :: Storable a => IO (Ptr a)
malloc = doMalloc undefined
doMalloc :: Storable a => a -> IO (Ptr a)
doMalloc dummy = mallocBytes (sizeOf dummy)
--- allocate given number of bytes of storage
+-- |Allocate given number of bytes of storage, equivalent to C\'s @malloc()@.
--
mallocBytes :: Int -> IO (Ptr a)
mallocBytes size = failWhenNULL "malloc" (_malloc (fromIntegral size))
--- temporarily allocate space for a storable type
+-- |Temporarily allocate space for a storable type.
--
--- * the pointer passed as an argument to the function must *not* escape from
--- this function; in other words, in `alloca f' the allocated storage must
--- not be used after `f' returns
+-- * the pointer passed as an argument to the function must /not/ escape from
+-- this function; in other words, in @alloca f@ the allocated storage must
+-- not be used after @f@ returns
--
alloca :: Storable a => (Ptr a -> IO b) -> IO b
alloca = doAlloca undefined
doAlloca :: Storable a => a -> (Ptr a -> IO b) -> IO b
doAlloca dummy = allocaBytes (sizeOf dummy)
--- temporarily allocate the given number of bytes of storage
+-- |Temporarily allocate the given number of bytes of storage.
--
--- * the pointer passed as an argument to the function must *not* escape from
--- this function; in other words, in `allocaBytes n f' the allocated storage
--- must not be used after `f' returns
+-- * the pointer passed as an argument to the function must /not/ escape from
+-- this function; in other words, in @allocaBytes n f@ the allocated storage
+-- must not be used after @f@ returns
--
#ifdef __GLASGOW_HASKELL__
allocaBytes :: Int -> (Ptr a -> IO b) -> IO b
allocaBytes size = bracket (mallocBytes size) free
#endif
--- adjust a malloc'ed storage area to the given size
+-- |Adjust a malloc\'ed storage area to the given size (equivalent to
+-- C\'s @realloc()@).
--
reallocBytes :: Ptr a -> Int -> IO (Ptr a)
reallocBytes ptr size =
failWhenNULL "realloc" (_realloc ptr (fromIntegral size))
--- free malloc'ed storage
+-- |Free malloc\'ed storage (equivalent to
+-- C\'s @free()@)
--
free :: Ptr a -> IO ()
free = _free
-----------------------------------------------------------------------------
module Foreign.Marshal.Array (
+ -- * Marshalling arrays
- -- allocation
+ -- ** Allocation
--
mallocArray, -- :: Storable a => Int -> IO (Ptr a)
mallocArray0, -- :: Storable a => Int -> IO (Ptr a)
reallocArray, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)
reallocArray0, -- :: Storable a => Ptr a -> Int -> IO (Ptr a)
- -- marshalling
+ -- ** Marshalling
--
peekArray, -- :: Storable a => Int -> Ptr a -> IO [a]
peekArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
pokeArray, -- :: Storable a => Ptr a -> [a] -> IO ()
pokeArray0, -- :: Storable a => a -> Ptr a -> [a] -> IO ()
- -- combined allocation and marshalling
+ -- ** Combined allocation and marshalling
--
newArray, -- :: Storable a => [a] -> IO (Ptr a)
newArray0, -- :: Storable a => a -> [a] -> IO (Ptr a)
withArray, -- :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray0, -- :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
- -- copying (argument order: destination, source)
- --
+ -- ** Copying
+
+ -- | (argument order: destination, source)
copyArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
moveArray, -- :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
- -- finding the length
+ -- ** Finding the length
--
lengthArray0, -- :: (Storable a, Eq a) => a -> Ptr a -> IO Int
- -- indexing
+ -- ** Indexing
--
advancePtr, -- :: Storable a => Ptr a -> Int -> Ptr a
) where
#ifdef __GLASGOW_HASKELL__
import Foreign.Ptr (Ptr, plusPtr)
import GHC.Storable (Storable(sizeOf,peekElemOff,pokeElemOff))
-import Foreign.Marshal.Alloc (mallocBytes, allocaBytes, reallocBytes)
+import Foreign.Marshal.Alloc (alloca, mallocBytes, allocaBytes, reallocBytes)
import Foreign.Marshal.Utils (copyBytes, moveBytes)
import GHC.IOBase
import GHC.Num
-- allocation
-- ----------
--- allocate storage for the given number of elements of a storable type
+-- |Allocate storage for the given number of elements of a storable type.
--
mallocArray :: Storable a => Int -> IO (Ptr a)
mallocArray = doMalloc undefined
doMalloc :: Storable a => a -> Int -> IO (Ptr a)
doMalloc dummy size = mallocBytes (size * sizeOf dummy)
--- like `mallocArray', but add an extra element to signal the end of the array
+-- |Like 'mallocArray', but add an extra element to signal the end of the array
--
mallocArray0 :: Storable a => Int -> IO (Ptr a)
mallocArray0 size = mallocArray (size + 1)
--- temporarily allocate space for the given number of elements
+-- |Temporarily allocate space for the given number of elements.
--
--- * see `MarshalAlloc.alloca' for the storage lifetime constraints
+-- * see 'Foreign.Marshal.Alloc.alloca' for the storage lifetime constraints
--
allocaArray :: Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray = doAlloca undefined
doAlloca :: Storable a => a -> Int -> (Ptr a -> IO b) -> IO b
doAlloca dummy size = allocaBytes (size * sizeOf dummy)
--- like `allocaArray', but add an extra element to signal the end of the array
+-- |Like 'allocaArray', but add an extra element to signal the end of the array
--
allocaArray0 :: Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray0 size = allocaArray (size + 1)
--- adjust the size of an array
+-- |Adjust the size of an array
--
reallocArray :: Storable a => Ptr a -> Int -> IO (Ptr a)
reallocArray = doRealloc undefined
doRealloc :: Storable a => a -> Ptr a -> Int -> IO (Ptr a)
doRealloc dummy ptr size = reallocBytes ptr (size * sizeOf dummy)
--- adjust the size of an array while adding an element for the end marker
+-- |Adjust the size of an array while adding an element for the end marker
--
reallocArray0 :: Storable a => Ptr a -> Int -> IO (Ptr a)
reallocArray0 ptr size = reallocArray ptr (size + 1)
-- marshalling
-- -----------
--- convert an array of given length into a Haskell list. This version
+-- |Convert an array of given length into a Haskell list. This version
-- traverses the array backwards using an accumulating parameter,
-- which uses constant stack space. The previous version using mapM
-- needed linear stack space.
f 0 acc = do e <- peekElemOff ptr 0; return (e:acc)
f n acc = do e <- peekElemOff ptr n; f (n-1) (e:acc)
--- convert an array terminated by the given end marker into a Haskell list
+-- |Convert an array terminated by the given end marker into a Haskell list
--
peekArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO [a]
peekArray0 marker ptr = loop 0
rest <- loop (i+1)
return (val:rest)
--- write the list elements consecutive into memory
+-- |Write the list elements consecutive into memory
--
pokeArray :: Storable a => Ptr a -> [a] -> IO ()
pokeArray ptr vals = zipWithM_ (pokeElemOff ptr) [0..] vals
--- write the list elements consecutive into memory and terminate them with the
+-- |Write the list elements consecutive into memory and terminate them with the
-- given marker element
--
pokeArray0 :: Storable a => a -> Ptr a -> [a] -> IO ()
-- combined allocation and marshalling
-- -----------------------------------
--- write a list of storable elements into a newly allocated, consecutive
+-- |Write a list of storable elements into a newly allocated, consecutive
-- sequence of storable values
--
newArray :: Storable a => [a] -> IO (Ptr a)
pokeArray ptr vals
return ptr
--- write a list of storable elements into a newly allocated, consecutive
+-- |Write a list of storable elements into a newly allocated, consecutive
-- sequence of storable values, where the end is fixed by the given end marker
--
newArray0 :: Storable a => a -> [a] -> IO (Ptr a)
pokeArray0 marker ptr vals
return ptr
--- temporarily store a list of storable values in memory
+-- |Temporarily store a list of storable values in memory
--
withArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
withArray vals f =
where
len = length vals
--- like `withArray', but a terminator indicates where the array ends
+-- |Like 'withArray', but a terminator indicates where the array ends
--
withArray0 :: Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 marker vals f =
-- copying (argument order: destination, source)
-- -------
--- copy the given number of elements from the second array (source) into the
--- first array (destination); the copied areas may *not* overlap
+-- |Copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas may /not/ overlap
--
copyArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
copyArray = doCopy undefined
doCopy :: Storable a => a -> Ptr a -> Ptr a -> Int -> IO ()
doCopy dummy dest src size = copyBytes dest src (size * sizeOf dummy)
--- copy the given number of elements from the second array (source) into the
--- first array (destination); the copied areas *may* overlap
+-- |Copy the given number of elements from the second array (source) into the
+-- first array (destination); the copied areas /may/ overlap
--
moveArray :: Storable a => Ptr a -> Ptr a -> Int -> IO ()
moveArray = doMove undefined
-- finding the length
-- ------------------
--- return the number of elements in an array, excluding the terminator
+-- |Return the number of elements in an array, excluding the terminator
--
lengthArray0 :: (Storable a, Eq a) => a -> Ptr a -> IO Int
lengthArray0 marker ptr = loop 0
-- indexing
-- --------
--- advance a pointer into an array by the given number of elements
+-- |Advance a pointer into an array by the given number of elements
--
advancePtr :: Storable a => Ptr a -> Int -> Ptr a
advancePtr = doAdvance undefined
-----------------------------------------------------------------------------
module Foreign.Marshal.Error (
+ -- * Error utilities
- -- throw an exception on specific return values
+ -- |Throw an exception on specific return values
--
throwIf, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO a
throwIf_, -- :: (a -> Bool) -> (a -> String) -> IO a -> IO ()
-- => (a -> String) -> IO a -> IO ()
throwIfNull, -- :: String -> IO (Ptr a) -> IO (Ptr a)
- -- discard return value
+ -- Discard return value
--
void -- IO a -> IO ()
) where
-- exported functions
-- ------------------
--- guard an IO operation and throw an exception if the result meets the given
+-- |Guard an 'IO' operation and throw an exception if the result meets the given
-- predicate
--
--- * the second argument computes an error message from the result of the IO
+-- * the second argument computes an error message from the result of the 'IO'
-- operation
--
throwIf :: (a -> Bool) -> (a -> String) -> IO a -> IO a
res <- act
(if pred res then ioError . userError . msgfct else return) res
--- like `throwIf', but discarding the result
+-- |Like 'throwIf', but discarding the result
--
throwIf_ :: (a -> Bool) -> (a -> String) -> IO a -> IO ()
throwIf_ pred msgfct act = void $ throwIf pred msgfct act
--- guards against negative result values
+-- |Guards against negative result values
--
throwIfNeg :: (Ord a, Num a) => (a -> String) -> IO a -> IO a
throwIfNeg = throwIf (< 0)
--- like `throwIfNeg', but discarding the result
+-- |Like 'throwIfNeg', but discarding the result
--
throwIfNeg_ :: (Ord a, Num a) => (a -> String) -> IO a -> IO ()
throwIfNeg_ = throwIf_ (< 0)
--- guards against null pointers
+-- |Guards against null pointers
--
throwIfNull :: String -> IO (Ptr a) -> IO (Ptr a)
throwIfNull = throwIf (== nullPtr) . const
--- discard the return value of an IO action
+-- |Discard the return value of an 'IO' action
--
void :: IO a -> IO ()
void act = act >> return ()
-----------------------------------------------------------------------------
module Foreign.Marshal.Utils (
+ -- * General marshalling utilities
- -- combined allocation and marshalling
+ -- ** Combined allocation and marshalling
--
withObject, -- :: Storable a => a -> (Ptr a -> IO b) -> IO b
{- FIXME: should be `with' -}
new, -- :: Storable a => a -> IO (Ptr a)
- -- marshalling of Boolean values (non-zero corresponds to `True')
+ -- ** Marshalling of Boolean values (non-zero corresponds to 'True')
--
fromBool, -- :: Num a => Bool -> a
toBool, -- :: Num a => a -> Bool
- -- marshalling of Maybe values
+ -- ** Marshalling of Maybe values
--
maybeNew, -- :: ( a -> IO (Ptr a))
-- -> (Maybe a -> IO (Ptr a))
maybePeek, -- :: (Ptr a -> IO b )
-- -> (Ptr a -> IO (Maybe b))
- -- marshalling lists of storable objects
+ -- ** Marshalling lists of storable objects
--
withMany, -- :: (a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
- -- Haskellish interface to memcpy and memmove
- -- (argument order: destination, source)
- --
+ -- ** 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
-- combined allocation and marshalling
-- -----------------------------------
--- allocate storage for a value and marshal it into this storage
+-- |Allocate storage for a value and marshal it into this storage
--
new :: Storable a => a -> IO (Ptr a)
new val =
poke ptr val
return ptr
--- allocate temporary storage for a value and marshal it into this storage
+-- |Allocate temporary storage for a value and marshal it into this storage
--
--- * see the life time constraints imposed by `alloca'
+-- * see the life time constraints imposed by 'alloca'
--
{- FIXME: should be called `with' -}
withObject :: Storable a => a -> (Ptr a -> IO b) -> IO b
return res
--- marshalling of Boolean values (non-zero corresponds to `True')
+-- marshalling of Boolean values (non-zero corresponds to 'True')
-- -----------------------------
--- convert a Haskell Boolean to its numeric representation
+-- |Convert a Haskell 'Bool' 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
+-- |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'
+-- |Allocate storage and marshall a storable value wrapped into a 'Maybe'
--
--- * the `nullPtr' is used to represent `Nothing'
+-- * 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'
+-- |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'
+-- |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
-- marshalling lists of storable objects
-- -------------------------------------
--- replicates a withXXX combinator over a list of objects, yielding a list of
+-- |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
-- 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
+-- |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)
--- copies the given number of elements from the second area (source) into the
--- first (destination); the copied areas *may* overlap
+-- |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)
-- auxilliary routines
-- -------------------
--- basic C routines needed for memory copying
+-- |Basic C routines needed for memory copying
--
foreign import ccall unsafe memcpy :: Ptr a -> Ptr a -> CSize -> IO ()
foreign import ccall unsafe memmove :: Ptr a -> Ptr a -> CSize -> IO ()
-- Stability : provisional
-- Portability : portable
--
--- Pointer types.
+-- The "Ptr" module provides typed pointers to foreign data. It is part
+-- of the Foreign Function Interface (FFI) and will normally be
+-- imported via the "Foreign" module.
--
-----------------------------------------------------------------------------
module Foreign.Ptr (
- --------------------------------------------------------------------
- -- Data pointers.
+
+ -- * Data pointers
- Ptr(..), -- data Ptr a
+ Ptr, -- data Ptr a
nullPtr, -- :: Ptr a
castPtr, -- :: Ptr a -> Ptr b
plusPtr, -- :: Ptr a -> Int -> Ptr b
alignPtr, -- :: Ptr a -> Int -> Ptr a
minusPtr, -- :: Ptr a -> Ptr b -> Int
- --------------------------------------------------------------------
- -- Function pointers.
+ -- * Function pointers
- FunPtr(..), -- data FunPtr a
+ FunPtr, -- data FunPtr a
nullFunPtr, -- :: FunPtr a
castFunPtr, -- :: FunPtr a -> FunPtr b
castFunPtrToPtr, -- :: FunPtr a -> Ptr b
-- Stability : provisional
-- Portability : portable
--
--- Stable pointers.
+-- This module is part of the Foreign Function Interface (FFI) and will usually
+-- be imported via the module "Foreign".
--
-----------------------------------------------------------------------------
+
module Foreign.StablePtr
- ( StablePtr, -- abstract
+ ( -- * Stable references to Haskell values
+ StablePtr, -- abstract
, newStablePtr -- :: a -> IO (StablePtr a)
, deRefStablePtr -- :: StablePtr a -> IO a
, freeStablePtr -- :: StablePtr a -> IO ()
, castStablePtrToPtr -- :: StablePtr a -> Ptr ()
, castPtrToStablePtr -- :: Ptr () -> StablePtr a
+ , -- ** The C-side interface
+
+ -- $cinterface
) where
#ifdef __GLASGOW_HASKELL__
import GHC.Stable
import GHC.Err
#endif
+
+
+-- $cinterface
+--
+-- The following definition is available to C programs inter-operating with
+-- Haskell code when including the header @HsFFI.h@.
+--
+-- > typedef void *HsStablePtr; /* C representation of a StablePtr */
+--
+-- Note that no assumptions may be made about the values representing stable
+-- pointers. In fact, they need not even be valid memory addresses. The only
+-- guarantee provided is that if they are passed back to Haskell land, the
+-- function 'deRefStablePtr' will be able to reconstruct the
+-- Haskell value refereed to by the stable pointer.
-- Stability : provisional
-- Portability : portable
--
--- A class for primitive marshaling
+-- The module "Storable" provides most elementary support for
+-- marshalling and is part of the language-independent portion of the
+-- Foreign Function Interface (FFI), and will normally be imported via
+-- the "Foreign" module.
--
-----------------------------------------------------------------------------
module Foreign.Storable
- ( Storable(
+ ( -- * The 'Storable' class
+ Storable(
sizeOf, -- :: a -> Int
alignment, -- :: a -> Int
peekElemOff, -- :: Ptr a -> Int -> IO a
-- Data pointers.
data Ptr a = Ptr Addr# deriving (Eq, Ord)
+-- ^ A value of type @'Ptr' a@ represents a pointer to an object, or an
+-- array of objects, which may be marshalled to or from Haskell values
+-- of type @a@.
+--
+-- The type @a@ will normally be an instance of class
+-- 'Storable' which provides the marshalling operations.
+
+-- |The constant 'nullPtr' contains a distinguished value of 'Ptr'
+-- that is not associated with a valid memory location.
nullPtr :: Ptr a
nullPtr = Ptr nullAddr#
+-- |The 'castPtr' function casts a pointer from one type to another.
castPtr :: Ptr a -> Ptr b
castPtr (Ptr addr) = Ptr addr
+-- |Advances the given address by the given offset in bytes.
plusPtr :: Ptr a -> Int -> Ptr b
plusPtr (Ptr addr) (I# d) = Ptr (plusAddr# addr d)
+-- |Given an arbitrary address and an alignment constraint,
+-- 'alignPtr' yields the next higher address that fulfills the
+-- alignment constraint. An alignment constraint @x@ is fulfilled by
+-- any address divisible by @x@. This operation is idempotent.
alignPtr :: Ptr a -> Int -> Ptr a
alignPtr addr@(Ptr a) (I# i)
= case remAddr# a i of {
0# -> addr;
n -> Ptr (plusAddr# a (i -# n)) }
+-- |Computes the offset required to get from the first to the second
+-- argument. We have
+--
+-- > p2 == p1 \`'plusPtr'\` (p2 \`'minusPtr'\` p1)
minusPtr :: Ptr a -> Ptr b -> Int
minusPtr (Ptr a1) (Ptr a2) = I# (minusAddr# a1 a2)
-- Function pointers for the default calling convention.
data FunPtr a = FunPtr Addr# deriving (Eq, Ord)
+-- ^ A value of type @'FunPtr' a@ is a pointer to a piece of code. It
+-- may be the pointer to a C function or to a Haskell function created
+-- using @foreign export dynamic@. A @foreign export
+-- dynamic@ should normally be declared to produce a
+-- 'FunPtr' of the correct type. For example:
+--
+-- > type Compare = 'Int' -> 'Int' -> 'Bool'
+-- > foreign export dynamic mkCompare :: Compare -> 'IO' ('FunPtr' Compare)
+-- |The constant 'nullFunPtr' contains a
+-- distinguished value of 'Ptr' that is not
+-- associated with a valid memory location
nullFunPtr :: FunPtr a
nullFunPtr = FunPtr nullAddr#
+-- |Casts a 'FunPtr' to a 'FunPtr' of a different type
castFunPtr :: FunPtr a -> FunPtr b
castFunPtr (FunPtr addr) = FunPtr addr
+-- |Casts a 'FunPtr' to a 'Ptr'
castFunPtrToPtr :: FunPtr a -> Ptr b
castFunPtrToPtr (FunPtr addr) = Ptr addr
+-- |Casts a 'Ptr' to a 'FunPtr'
castPtrToFunPtr :: Ptr a -> FunPtr b
castPtrToFunPtr (Ptr addr) = FunPtr addr
in each of the peek/poke families.
\begin{code}
+{- |
+The member functions of this class facilitate writing values of
+primitive types to raw memory (which may have been allocated with the
+above mentioned routines) and reading values from blocks of raw
+memory. The class, furthermore, includes support for computing the
+storage requirements and alignment restrictions of storable types.
+
+Memory addresses are represented as values of type @'Ptr' a@, for some
+@a@ which is an instance of class 'Storable'. The type argument to
+'Ptr' helps provide some valuable type safety in FFI code (you can\'t
+mix pointers of different types without an explicit cast), while
+helping the Haskell type system figure out which marshalling method is
+needed for a given pointer.
+
+All marshalling between Haskell and a foreign language ultimately
+boils down to translating Haskell data structures into the binary
+representation of a corresponding data structure of the foreign
+language and vice versa. To code this marshalling in Haskell, it is
+necessary to manipulate primtive data types stored in unstructured
+memory blocks. The class 'Storable' facilitates this manipulation on
+all types for which it is instantiated, which are the standard basic
+types of Haskell, the fixed size @Int@ types ('Int8', 'Int16',
+'Int32', 'Int64'), the fixed size @Word@ types ('Word8', 'Word16',
+'Word32', 'Word64'), 'StablePtr', all types from "CTypes" and
+"CTypesISO", as well as 'Ptr'.
+
+Minimal complete definition: 'sizeOf', 'alignment', one of 'peek',
+'peekElemOff' and 'peekByteOff', and one of 'poke', 'pokeElemOff' and
+'pokeByteOff'.
+-}
+
class Storable a where
- -- sizeOf/alignment *never* use their first argument
sizeOf :: a -> Int
+ -- ^ Computes the storage requirements (in bytes) of the argument.
+ -- The value of the argument is not used.
+
alignment :: a -> Int
+ -- ^ Computes the alignment constraint of the argument. An
+ -- alignment constraint @x@ is fulfilled by any address divisible
+ -- by @x@. The value of the argument is not used.
- -- replacement for read-/write???OffAddr
peekElemOff :: Ptr a -> Int -> IO a
+ -- ^ Read a value from a memory area regarded as an array
+ -- of values of the same kind. The first argument specifies
+ -- the start address of the array and the second the index into
+ -- the array (the first element of the array has index
+ -- @0@). The following equality holds,
+ --
+ -- > peekElemOff addr idx = IOExts.fixIO $ \result ->
+ -- > peek (addr \`plusPtr\` (idx * sizeOf result))
+ --
+ -- Note that this is only a specification, not
+ -- necessarily the concrete implementation of the
+ -- function.
+
pokeElemOff :: Ptr a -> Int -> a -> IO ()
+ -- ^ Write a value to a memory area regarded as an array of
+ -- values of the same kind. The following equality holds:
+ --
+ -- > pokeElemOff addr idx x =
+ -- > poke (addr \`plusPtr\` (idx * sizeOf x)) x
- -- the same with *byte* offsets
peekByteOff :: Ptr b -> Int -> IO a
- pokeByteOff :: Ptr b -> Int -> a -> IO ()
+ -- ^ Read a value from a memory location given by a base
+ -- address and offset. The following equality holds:
+ --
+ -- > peekByteOff addr off = peek (addr \`plusPtr\` off)
- -- ... and with no offsets at all
+ pokeByteOff :: Ptr b -> Int -> a -> IO ()
+ -- ^ Write a value to a memory location given by a base
+ -- address and offset. The following equality holds:
+ --
+ -- > pokeByteOff addr off x = poke (addr \`plusPtr\` off) x
+
peek :: Ptr a -> IO a
- poke :: Ptr a -> a -> IO ()
+ -- ^ Read a value from the given memory location.
+ --
+ -- Note that the peek and poke functions might require properly
+ -- aligned addresses to function correctly. This is architecture
+ -- dependent; thus, portable code should ensure that when peeking or
+ -- poking values of some type @a@, the alignment
+ -- constraint for @a@, as given by the function
+ -- 'alignment' is fulfilled.
+ poke :: Ptr a -> a -> IO ()
+ -- ^ Write the given value to the given memory location. Alignment
+ -- restrictions might apply; see 'peek'.
+
-- circular default instances
peekElemOff = peekElemOff_ undefined
where peekElemOff_ :: a -> Ptr a -> Int -> IO a