5.14. ForeignObj

NOTE: this interface is deprecated. Please use ForeignPtr instead (see Section 5.15).

This module is part of the Foreign Function Interface (FFI) and will usually be imported via the module Foreign (see Section 5.13). The type ForeignObj 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 ForeignObjs and vanilla memory references of type Ptr a (Section 5.29) 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 ForeignObj. Typically, the finaliser will, then, invoke routines in the foreign language that free the resources bound by the foreign object.

5.14.1. The Standard Interface

data ForeignObj		-- abstract handle to foreign object
instance Eq ForeignObj

newForeignObj       :: Ptr a      -> IO () -> IO ForeignObj
addForeignFinalizer :: ForeignObj -> IO () -> IO () 
withForeignObj      :: ForeignObj -> (Ptr a -> IO b) -> IO b
touchForeignObj     :: ForeignObj -> IO ()
foreignObjToPtr     :: ForeignObj -> Ptr a  -- *unsafe* operation

The behaviour of the functions is as follows:

newForeignObj :: Ptr a -> IO () -> IO ForeignObj

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.

addForeignFinalizer :: ForeignObj -> 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.

withForeignObj :: ForeignObj -> (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 withForeignObj bracket.

touchForeignObj :: ForeignObj -> IO ()

This function ensures that the foreign object in question is alive at the given place in the sequence of IO actions. It tells that we are still interested in the object, even though we don't have anything more specific to do with a ForeignObj value, probably because we are playing with the address taken from it. In particular withForeignObj does a touchForeignObj after it executes the user action.

foreignObjToPtr :: ForeignObj -> Ptr a

Extract the plain memory reference contained in a foreign object. You should use withForeignObj instead of foreignObjToPtr whenever possible because the former function is safer.

This routine should be handled with a lot of care: The reference to the foreign object that is passed in a call to foreignObjToPtr may be the last reference to the object that exists in Haskell land. In this case, the finalisers of the foreign object may be activated any time after the call to foreignObjToPtr is evaluated. If the finalisers, for example, trigger deallocation of the foreign object's memory area, the Ptr a obtained by the call to foreignObjToPtr may be rendered invalid when garbage collection hits after the call. Whether this is a problem or not depends on the details of the finaliser code and the operations subsequently performed on the Ptr a.

touchForeignObj can help in ensuring that the foreign object is not finalised too early. A stable pointer (Section 5.34) can also be used to establish a guaranteed reference to the foreign object. The finalisers will, then, certainly not be run before StablePtr.freeStablePtr is used.

5.14.2. The Standard C-side Interface

The following definition is available to C programs inter-operating with Haskell code when including the header HsFFI.h.

typedef void* HsForeignObj;  /* C representation of a ForeignObj */

5.14.3. Deprecated Functions

The following functions are deprecated in the new FFI. Do not use the following functions if you are interested in portability. Instead of the indexXXX, readXXX, and writeXXX functions, use the module Storable (Section 5.35).

Most of these functions are here for legacy reasons and may just vanish one day. You have been warned.

foreignObjToAddr :: ForeignObj -> Addr   -- *unsafe* operation
writeForeignObj  :: ForeignObj -> Addr{-new value-} -> IO ()
makeForeignObj   :: Addr -> Addr -> IO ForeignObj

indexCharOffForeignObj   :: ForeignObj -> Int -> Char
indexIntOffForeignObj    :: ForeignObj -> Int -> Int
indexWordOffForeignObj   :: ForeignObj -> Int -> Word
indexAddrOffForeignObj   :: ForeignObj -> Int -> Addr
indexFloatOffForeignObj  :: ForeignObj -> Int -> Float
indexDoubleOffForeignObj :: ForeignObj -> Int -> Double
indexWord8OffForeignObj  :: ForeignObj -> Int -> Word8
indexWord16OffForeignObj :: ForeignObj -> Int -> Word16
indexWord32OffForeignObj :: ForeignObj -> Int -> Word32
indexWord64OffForeignObj :: ForeignObj -> Int -> Word64

indexInt8OffForeignObj  :: ForeignObj -> Int -> Int8
indexInt16OffForeignObj :: ForeignObj -> Int -> Int16
indexInt32OffForeignObj :: ForeignObj -> Int -> Int32
indexInt64OffForeignObj :: ForeignObj -> Int -> Int64

-- read value out of mutable memory
readCharOffForeignObj    :: ForeignObj -> Int -> IO Char
readIntOffForeignObj     :: ForeignObj -> Int -> IO Int
readWordOffForeignObj    :: ForeignObj -> Int -> IO Word
readAddrOffForeignObj    :: ForeignObj -> Int -> IO Addr
readFloatOffForeignObj   :: ForeignObj -> Int -> IO Float
readDoubleOffForeignObj  :: ForeignObj -> Int -> IO Double
readWord8OffForeignObj   :: ForeignObj -> Int -> IO Word8
readWord16OffForeignObj  :: ForeignObj -> Int -> IO Word16
readWord32OffForeignObj  :: ForeignObj -> Int -> IO Word32
readWord64OffForeignObj  :: ForeignObj -> Int -> IO Word64
readInt8OffForeignObj    :: ForeignObj -> Int -> IO Int8
readInt16OffForeignObj   :: ForeignObj -> Int -> IO Int16
readInt32OffForeignObj   :: ForeignObj -> Int -> IO Int32
readInt64OffForeignObj   :: ForeignObj -> Int -> IO Int64

writeCharOffForeignObj   :: ForeignObj -> Int -> Char   -> IO ()
writeIntOffForeignObj    :: ForeignObj -> Int -> Int    -> IO ()
writeWordOffForeignObj   :: ForeignObj -> Int -> Word   -> IO ()
writeAddrOffForeignObj   :: ForeignObj -> Int -> Addr   -> IO ()
writeFloatOffForeignObj  :: ForeignObj -> Int -> Float  -> IO ()
writeDoubleOffForeignObj :: ForeignObj -> Int -> Double -> IO ()
writeWord8OffForeignObj  :: ForeignObj -> Int -> Word8  -> IO ()
writeWord16OffForeignObj :: ForeignObj -> Int -> Word16 -> IO ()
writeWord32OffForeignObj :: ForeignObj -> Int -> Word32 -> IO ()
writeWord64OffForeignObj :: ForeignObj -> Int -> Word64 -> IO ()
writeInt8OffForeignObj   :: ForeignObj -> Int -> Int8   -> IO ()
writeInt16OffForeignObj  :: ForeignObj -> Int -> Int16  -> IO ()
writeInt32OffForeignObj  :: ForeignObj -> Int -> Int32  -> IO ()
writeInt64OffForeignObj  :: ForeignObj -> Int -> Int64  -> IO ()