-- |
-- Module : Foreign.ForeignPtr
-- Copyright : (c) The University of Glasgow 2001
--- License : BSD-style (see the file libraries/core/LICENSE)
+-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : ffi@haskell.org
-- Stability : provisional
module Foreign.ForeignPtr
(
-- * Finalised data pointers
- ForeignPtr, -- abstract, instance of: Eq
+ 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
, foreignPtrToPtr -- :: ForeignPtr a -> Ptr a
, touchForeignPtr -- :: ForeignPtr a -> IO ()
, castForeignPtr -- :: ForeignPtr a -> ForeignPtr b
+
+#ifndef __NHC__
+ , mallocForeignPtr -- :: Storable a => IO (ForeignPtr a)
+ , mallocForeignPtrBytes -- :: Int -> IO (ForeignPtr a)
+#endif
)
where
+#ifndef __NHC__
import Foreign.Ptr
+import Foreign.Storable
import Data.Dynamic
+#endif
#ifdef __GLASGOW_HASKELL__
import GHC.Base
import GHC.IOBase
import GHC.Num
+import GHC.Ptr ( Ptr(..) )
import GHC.Err
+import GHC.Show
+#endif
+
+#ifdef __NHC__
+import NHC.FFI
+ ( ForeignPtr
+ , newForeignPtr
+ , addForeignPtrFinalizer
+ , withForeignPtr
+ , foreignPtrToPtr
+ , touchForeignPtr
+ , castForeignPtr
+ )
+#endif
+
+#ifdef __HUGS__
+import Hugs.ForeignPtr
#endif
+#ifndef __NHC__
#include "Dynamic.h"
INSTANCE_TYPEABLE1(ForeignPtr,foreignPtrTc,"ForeignPtr")
+#endif
#ifdef __GLASGOW_HASKELL__
-- |The type 'ForeignPtr' represents references to objects that are
-- type argument of 'ForeignPtr' should normally be an instance of
-- class 'Storable'.
--
-data ForeignPtr a = ForeignPtr ForeignObj#
+data ForeignPtr a
+ = ForeignPtr ForeignObj#
+ | MallocPtr (MutableByteArray# RealWorld)
-instance CCallable (ForeignPtr a)
+instance Eq (ForeignPtr a) where
+ p == q = foreignPtrToPtr p == foreignPtrToPtr q
-eqForeignPtr :: ForeignPtr a -> ForeignPtr a -> Bool
-eqForeignPtr (ForeignPtr fo1#) (ForeignPtr fo2#) = eqForeignObj# fo1# fo2#
+instance Show (ForeignPtr a) where
+ showsPrec p f = showsPrec p (foreignPtrToPtr f)
-instance Eq (ForeignPtr a) where
- p == q = eqForeignPtr p q
- p /= q = not (eqForeignPtr p q)
newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a)
-- ^Turns a plain memory reference into a foreign object
addForeignPtrFinalizer fObj finalizer
return fObj
+-- | allocates some memory and returns a ForeignPtr to it. The memory
+-- will be released automatically when the ForeignPtr is discarded.
+--
+-- @mallocForeignPtr@ is equivalent to
+--
+-- > do { p <- malloc; newForeignPtr p free }
+--
+-- although it may be implemented differently internally. You may not
+-- assume that the memory returned by 'mallocForeignPtr' has been
+-- allocated with C's @malloc()@.
+
+mallocForeignPtr :: Storable a => IO (ForeignPtr a)
+mallocForeignPtr = doMalloc undefined
+ where doMalloc :: Storable a => a -> IO (ForeignPtr a)
+ doMalloc a = IO $ \s ->
+ case newPinnedByteArray# size s of { (# s, mbarr# #) ->
+ (# s, MallocPtr mbarr# #)
+ }
+ where (I# size) = sizeOf a
+
+-- | similar to 'mallocForeignPtr', except that the size of the memory required
+-- is given explicitly as a number of bytes.
+mallocForeignPtrBytes :: Int -> IO (ForeignPtr a)
+mallocForeignPtrBytes (I# size) = IO $ \s ->
+ case newPinnedByteArray# size s of { (# s, mbarr# #) ->
+ (# s, MallocPtr mbarr# #)
+ }
+
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, () #) }
+addForeignPtrFinalizer (MallocPtr fo) finalizer =
+ IO $ \s -> case mkWeak# fo () finalizer s of { (# s1, w #) -> (# s1, () #) }
mkForeignPtr :: Ptr a -> IO (ForeignPtr a) {- not exported -}
mkForeignPtr (Ptr obj) = IO ( \ s# ->
-- until the interior pointer is no longer referenced.
touchForeignPtr (ForeignPtr fo)
= IO $ \s -> case touch# fo s of s -> (# s, () #)
+touchForeignPtr (MallocPtr 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
-- 'touchForeignPtr'. However, the later routines
-- are occasionally preferred in tool generated marshalling code.
foreignPtrToPtr (ForeignPtr fo) = Ptr (foreignObjToAddr# fo)
+foreignPtrToPtr (MallocPtr fo) = Ptr (byteArrayContents# (unsafeCoerce# fo))
castForeignPtr :: ForeignPtr a -> ForeignPtr b
-- ^This function casts a 'ForeignPtr'
-- parameterised by one type into another type.
castForeignPtr (ForeignPtr a) = ForeignPtr a
+castForeignPtr (MallocPtr a) = MallocPtr a
#endif