From 7c83378f249fe74b09739ed2faf1af66c992f77b Mon Sep 17 00:00:00 2001 From: ross Date: Fri, 25 Jun 2004 10:42:48 +0000 Subject: [PATCH] [project @ 2004-06-25 10:42:48 by ross] more Ptr/FunPtr documentation --- Foreign/Ptr.hs | 4 ++++ GHC/Ptr.lhs | 69 +++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Foreign/Ptr.hs b/Foreign/Ptr.hs index 514de59..a7db561 100644 --- a/Foreign/Ptr.hs +++ b/Foreign/Ptr.hs @@ -89,6 +89,10 @@ instance Show (FunPtr a) where showsPrec p = showsPrec p . castFunPtrToPtr #endif +-- | Release the storage associated with the given 'FunPtr', which +-- must have been obtained from a wrapper stub. This should be called +-- whenever the return value from a foreign import wrapper function is +-- no longer required; otherwise, the storage it uses will leak. foreign import ccall unsafe "freeHaskellFunctionPtr" freeHaskellFunPtr :: FunPtr a -> IO () #endif diff --git a/GHC/Ptr.lhs b/GHC/Ptr.lhs index 7f43745..1fbfeb6 100644 --- a/GHC/Ptr.lhs +++ b/GHC/Ptr.lhs @@ -26,9 +26,11 @@ data Ptr a = Ptr Addr# deriving (Eq, Ord) -- 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 +-- The type @a@ will often be an instance of class -- 'Foreign.Storable.Storable' which provides the marshalling operations. - +-- However this is not essential, and you can provide your own operations +-- to access the pointer. For example you might write small foreign +-- functions to get or set the fields of a C @struct@. -- |The constant 'nullPtr' contains a distinguished value of 'Ptr' -- that is not associated with a valid memory location. @@ -64,30 +66,71 @@ 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: +-- ^ A value of type @'FunPtr' a@ is a pointer to a function callable +-- from foreign code. The type @a@ will normally be a /foreign type/, +-- a function type with zero or more arguments where +-- +-- * the argument types are /marshallable foreign types/, +-- i.e. 'Char', 'Int', 'Prelude.Double', 'Prelude.Float', +-- 'Bool', 'Data.Int.Int8', 'Data.Int.Int16', 'Data.Int.Int32', +-- 'Data.Int.Int64', 'Data.Word.Word8', 'Data.Word.Word16', +-- 'Data.Word.Word32', 'Data.Word.Word64', @'Ptr' a@, @'FunPtr' a@, +-- @'Foreign.StablePtr.StablePtr' a@ or a renaming of any of these +-- using @newtype@. +-- +-- * the return type is either a marshallable foreign type or has the form +-- @'Prelude.IO' t@ where @t@ is a marshallable foreign type or @()@. +-- +-- A value of type @'FunPtr' a@ may be a pointer to a foreign function, +-- either returned by another foreign function or imported with a +-- a static address import like +-- +-- > foreign import ccall "stdlib.h &free" +-- > p_free :: FunPtr (Ptr a -> IO ()) +-- +-- or a pointer to a Haskell function created using a /wrapper/ stub +-- declared to produce a 'FunPtr' of the correct type. For example: -- -- > type Compare = Int -> Int -> Bool --- > foreign export dynamic mkCompare :: Compare -> IO (FunPtr Compare) +-- > foreign import ccall "wrapper" +-- > mkCompare :: Compare -> IO (FunPtr Compare) +-- +-- Calls to wrapper stubs like @mkCompare@ allocate storage, which +-- should be released with 'Foreign.Ptr.freeHaskellFunPtr' when no +-- longer required. +-- +-- To convert 'FunPtr' values to corresponding Haskell functions, one +-- can define a /dynamic/ stub for the specific foreign type, e.g. +-- +-- > type IntFunction = CInt -> IO () +-- > foreign import ccall "dynamic" +-- > mkFun :: FunPtr IntFunction -> IntFunction -- |The constant 'nullFunPtr' contains a --- distinguished value of 'Ptr' that is not --- associated with a valid memory location +-- distinguished value of 'FunPtr' 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 +-- |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' +-- |Casts a 'FunPtr' to a 'Ptr'. +-- +-- /Note:/ this is valid only on architectures where data and function +-- pointers range over the same set of addresses, and should only be used +-- for bindings to external libraries whose interface already relies on +-- this assumption. castFunPtrToPtr :: FunPtr a -> Ptr b castFunPtrToPtr (FunPtr addr) = Ptr addr --- |Casts a 'Ptr' to a 'FunPtr' +-- |Casts a 'Ptr' to a 'FunPtr'. +-- +-- /Note:/ this is valid only on architectures where data and function +-- pointers range over the same set of addresses, and should only be used +-- for bindings to external libraries whose interface already relies on +-- this assumption. castPtrToFunPtr :: Ptr a -> FunPtr b castPtrToFunPtr (Ptr addr) = FunPtr addr \end{code} -- 1.7.10.4