[project @ 2002-05-09 13:13:28 by simonmar]
authorsimonmar <unknown>
Thu, 9 May 2002 13:14:02 +0000 (13:14 +0000)
committersimonmar <unknown>
Thu, 9 May 2002 13:14:02 +0000 (13:14 +0000)
Add documentation Haddock-style

Foreign/ForeignPtr.hs
Foreign/Marshal/Alloc.hs
Foreign/Marshal/Array.hs
Foreign/Marshal/Error.hs
Foreign/Marshal/Utils.hs
Foreign/Ptr.hs
Foreign/StablePtr.hs
Foreign/Storable.hs
GHC/Ptr.lhs
GHC/Storable.lhs

index 43c3325..705bf1f 100644 (file)
@@ -9,13 +9,16 @@
 -- 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
@@ -39,7 +42,24 @@ import GHC.Err
 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
@@ -50,12 +70,24 @@ instance Eq (ForeignPtr a) where
     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, () #) }
 
@@ -65,18 +97,72 @@ mkForeignPtr (Ptr obj) =  IO ( \ s# ->
       (# 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
 
index d02ef75..7567743 100644 (file)
@@ -14,6 +14,7 @@
 -----------------------------------------------------------------------------
 
 module Foreign.Marshal.Alloc (
+  -- * Allocation
   malloc,       -- :: Storable a =>        IO (Ptr a)
   mallocBytes,  -- ::               Int -> IO (Ptr a)
 
@@ -43,7 +44,9 @@ import GHC.Base
 -- 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
@@ -51,16 +54,16 @@ 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
@@ -68,11 +71,11 @@ 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
@@ -90,13 +93,15 @@ 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
index 55b9c11..002961e 100644 (file)
@@ -15,8 +15,9 @@
 -----------------------------------------------------------------------------
 
 module Foreign.Marshal.Array (
+  -- * Marshalling arrays
 
-  -- allocation
+  -- ** Allocation
   --
   mallocArray,    -- :: Storable a => Int -> IO (Ptr a)
   mallocArray0,   -- :: Storable a => Int -> IO (Ptr a)
@@ -27,7 +28,7 @@ module Foreign.Marshal.Array (
   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]
@@ -35,7 +36,7 @@ module Foreign.Marshal.Array (
   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)
@@ -43,16 +44,17 @@ module Foreign.Marshal.Array (
   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
@@ -62,7 +64,7 @@ import Control.Monad
 #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
@@ -74,7 +76,7 @@ import GHC.Base
 -- 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
@@ -82,14 +84,14 @@ 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
@@ -97,12 +99,12 @@ 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
@@ -110,7 +112,7 @@ 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)
@@ -119,7 +121,7 @@ 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.
@@ -131,7 +133,7 @@ peekArray size ptr | size <= 0 = return []
     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
@@ -142,12 +144,12 @@ 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 ()
@@ -159,7 +161,7 @@ pokeArray0 marker ptr vals  = do
 -- 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)
@@ -168,7 +170,7 @@ newArray vals  = do
   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)
@@ -177,7 +179,7 @@ newArray0 marker vals  = do
   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  =
@@ -188,7 +190,7 @@ 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  =
@@ -203,8 +205,8 @@ 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
@@ -212,8 +214,8 @@ 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
@@ -225,7 +227,7 @@ 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
@@ -238,7 +240,7 @@ 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
index 1020f8a..889ab65 100644 (file)
@@ -14,8 +14,9 @@
 -----------------------------------------------------------------------------
 
 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 ()
@@ -25,7 +26,7 @@ module Foreign.Marshal.Error (
                 -- =>                (a -> String) -> IO a       -> IO ()
   throwIfNull,   -- ::                String        -> IO (Ptr a) -> IO (Ptr a)
 
-  -- discard return value
+  -- Discard return value
   --
   void           -- IO a -> IO ()
 ) where
@@ -41,10 +42,10 @@ import GHC.IOBase
 -- 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
@@ -53,27 +54,27 @@ throwIf pred msgfct act  =
     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 ()
index c8a5f74..87881b6 100644 (file)
 -----------------------------------------------------------------------------
 
 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))
@@ -35,13 +36,13 @@ module Foreign.Marshal.Utils (
   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
@@ -62,7 +63,7 @@ import GHC.Base
 -- 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  = 
@@ -71,9 +72,9 @@ 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
@@ -84,16 +85,16 @@ withObject val f  =
     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)
@@ -102,23 +103,23 @@ 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
@@ -128,7 +129,7 @@ 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
@@ -143,14 +144,14 @@ withMany withFoo (x:xs) f = withFoo x $ \x' ->
 -- 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)
@@ -159,7 +160,7 @@ 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 ()
index 0544486..4cf8700 100644 (file)
@@ -9,25 +9,26 @@
 -- 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
index 1b169d0..9b1bb9b 100644 (file)
@@ -9,20 +9,40 @@
 -- 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.
index 90b655d..9286e9c 100644 (file)
@@ -9,12 +9,16 @@
 -- 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
index 5c6191f..ab0e6e1 100644 (file)
@@ -22,22 +22,41 @@ import GHC.Base
 -- 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)
 
@@ -48,16 +67,30 @@ instance CReturnable (Ptr a)
 -- 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
 
index 7ffadf8..7441272 100644 (file)
@@ -54,24 +54,95 @@ Minimal complete definition: sizeOf, alignment, and one definition
 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