    {-# LANGUAGE CPP #-}
    {-# OPTIONS_HADDOCK hide #-}
    --  GIMP Toolkit (GTK) FFI extras and version dependencies
    --
    --  Author : Axel Simon
    --
    --  Created: 22 June 2001
    --
    --  Copyright (C) 1999-2005 Axel Simon
    --
    --  This library is free software; you can redistribute it and/or
    --  modify it under the terms of the GNU Lesser General Public
    --  License as published by the Free Software Foundation; either
    --  version 2.1 of the License, or (at your option) any later version.
    --
    --  This library is distributed in the hope that it will be useful,
    --  but WITHOUT ANY WARRANTY; without even the implied warranty of
    --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    --  Lesser General Public License for more details.
    --
    -- #hide

    -- |
    --
    -- This module serves as an impedance matcher for different compiler
    -- versions. It also adds a few FFI utility functions.
    --

    module System.Glib.FFI (
      nullForeignPtr,
      maybeNull,
      newForeignPtr,
      withForeignPtrs,
    #if MIN_VERSION_base(4,4,0)
      unsafePerformIO,
      unsafeForeignPtrToPtr,
    #endif
      module Foreign,
      module Foreign.C
      ) where

    -- We should almost certainly not be using the standard free function anywhere
    -- in the glib or gtk bindings, so we do not re-export it from this module.

    import Foreign.C

    #if MIN_VERSION_base(4,4,0)
    import Foreign hiding (unsafePerformIO, unsafeForeignPtrToPtr, newForeignPtr, free)
    import System.IO.Unsafe (unsafePerformIO)

    import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
    #else
    import Foreign hiding (newForeignPtr, free)
    #endif

    import qualified Foreign.Concurrent

    newForeignPtr :: Ptr a -> FinalizerPtr a -> IO (ForeignPtr a)
    newForeignPtr :: Ptr a -> FinalizerPtr a -> IO (ForeignPtr a)
    newForeignPtr p :: Ptr a
    p finalizer :: FinalizerPtr a
    finalizer
       = Ptr a -> IO () -> IO (ForeignPtr a)
    forall a. Ptr a -> IO () -> IO (ForeignPtr a)
    Foreign.Concurrent.newForeignPtr Ptr a
    p (FinalizerPtr a -> Ptr a -> IO ()
    forall a. FinalizerPtr a -> Ptr a -> IO ()
    mkFinalizer FinalizerPtr a
    finalizer Ptr a
    p)

    foreign import ccall "dynamic"
       mkFinalizer :: FinalizerPtr a -> Ptr a -> IO ()

    nullForeignPtr :: ForeignPtr a
    nullForeignPtr :: ForeignPtr a
    nullForeignPtr = IO (ForeignPtr a) -> ForeignPtr a
    forall a. IO a -> a
    unsafePerformIO (IO (ForeignPtr a) -> ForeignPtr a)
    -> IO (ForeignPtr a) -> ForeignPtr a
    forall a b. (a -> b) -> a -> b
    $ Ptr a -> IO (ForeignPtr a)
    forall a. Ptr a -> IO (ForeignPtr a)
    newForeignPtr_ Ptr a
    forall a. Ptr a
    nullPtr

    -- This is useful when it comes to marshaling lists of GObjects
    --
    withForeignPtrs :: [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b
    withForeignPtrs :: [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b
    withForeignPtrs fptrs :: [ForeignPtr a]
    fptrs body :: [Ptr a] -> IO b
    body = do
      b
    result <- [Ptr a] -> IO b
    body ((ForeignPtr a -> Ptr a) -> [ForeignPtr a] -> [Ptr a]
    forall a b. (a -> b) -> [a] -> [b]
    map ForeignPtr a -> Ptr a
    forall a. ForeignPtr a -> Ptr a
    unsafeForeignPtrToPtr [ForeignPtr a]
    fptrs)
      (ForeignPtr a -> IO ()) -> [ForeignPtr a] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ForeignPtr a -> IO ()
    forall a. ForeignPtr a -> IO ()
    touchForeignPtr [ForeignPtr a]
    fptrs
      b -> IO b
    forall (m :: * -> *) a. Monad m => a -> m a
    return b
    result

    -- A marshaling utility function that is used by the code produced by the code
    -- generator to marshal return values that can be null
    maybeNull :: (IO (Ptr a) -> IO a) -> IO (Ptr a) -> IO (Maybe a)
    maybeNull :: (IO (Ptr a) -> IO a) -> IO (Ptr a) -> IO (Maybe a)
    maybeNull marshal :: IO (Ptr a) -> IO a
    marshal genPtr :: IO (Ptr a)
    genPtr = do
      Ptr a
    ptr <- IO (Ptr a)
    genPtr
      if Ptr a
    ptr Ptr a -> Ptr a -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr a
    forall a. Ptr a
    nullPtr
        then Maybe a -> IO (Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe a
    forall a. Maybe a
    Nothing
        else do a
    result <- IO (Ptr a) -> IO a
    marshal (Ptr a -> IO (Ptr a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Ptr a
    ptr)
                Maybe a -> IO (Maybe a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> Maybe a
    forall a. a -> Maybe a
    Just a
    result)