    {-# LANGUAGE CPP                      #-}
    {-# LANGUAGE EmptyDataDecls           #-}
    {-# LANGUAGE ForeignFunctionInterface #-}
    {-# LANGUAGE CApiFFI                  #-}
    module OpenSSL.DH.Internal (
        DH_,
        DHP,
        withDHPPtr,
        wrapDHPPtrWith,
        wrapDHPPtr,
        DH,
        withDHPtr,
        wrapDHPtrWith,
        wrapDHPtr,
        asDH,
        asDHP
      ) where

    import Foreign.Ptr (Ptr)
    import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)
    import qualified Foreign.Concurrent as FC

    #if !MIN_VERSION_base(4,8,0)
    import Control.Applicative ((<$>))
    #endif

    data {-# CTYPE "openssl/dh.h" "DH" #-} DH_
    newtype DHP = DHP (ForeignPtr DH_)

    withDHPPtr :: DHP -> (Ptr DH_ -> IO a) -> IO a
    withDHPPtr :: forall a. DHP -> (Ptr DH_ -> IO a) -> IO a
    withDHPPtr (DHP ForeignPtr DH_
    fp) = ForeignPtr DH_ -> (Ptr DH_ -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr DH_
    fp

    wrapDHPPtrWith :: (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DHP
    wrapDHPPtrWith :: (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DHP
    wrapDHPPtrWith Ptr DH_ -> IO ()
    fin Ptr DH_
    p = ForeignPtr DH_ -> DHP
    DHP (ForeignPtr DH_ -> DHP) -> IO (ForeignPtr DH_) -> IO DHP
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr DH_ -> IO () -> IO (ForeignPtr DH_)
    forall a. Ptr a -> IO () -> IO (ForeignPtr a)
    FC.newForeignPtr Ptr DH_
    p (Ptr DH_ -> IO ()
    fin Ptr DH_
    p)

    wrapDHPPtr :: Ptr DH_ -> IO DHP
    wrapDHPPtr :: Ptr DH_ -> IO DHP
    wrapDHPPtr = (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DHP
    wrapDHPPtrWith Ptr DH_ -> IO ()
    _DH_free

    newtype DH = DH (ForeignPtr DH_)

    withDHPtr :: DH -> (Ptr DH_ -> IO a) -> IO a
    withDHPtr :: forall a. DH -> (Ptr DH_ -> IO a) -> IO a
    withDHPtr (DH ForeignPtr DH_
    fp) = ForeignPtr DH_ -> (Ptr DH_ -> IO a) -> IO a
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr DH_
    fp

    wrapDHPtrWith :: (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DH
    wrapDHPtrWith :: (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DH
    wrapDHPtrWith Ptr DH_ -> IO ()
    fin Ptr DH_
    p = ForeignPtr DH_ -> DH
    DH (ForeignPtr DH_ -> DH) -> IO (ForeignPtr DH_) -> IO DH
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr DH_ -> IO () -> IO (ForeignPtr DH_)
    forall a. Ptr a -> IO () -> IO (ForeignPtr a)
    FC.newForeignPtr Ptr DH_
    p (Ptr DH_ -> IO ()
    fin Ptr DH_
    p)

    wrapDHPtr :: Ptr DH_ -> IO DH
    wrapDHPtr :: Ptr DH_ -> IO DH
    wrapDHPtr = (Ptr DH_ -> IO ()) -> Ptr DH_ -> IO DH
    wrapDHPtrWith Ptr DH_ -> IO ()
    _DH_free

    asDH :: DHP -> DH
    asDH :: DHP -> DH
    asDH (DHP ForeignPtr DH_
    fp) = ForeignPtr DH_ -> DH
    DH ForeignPtr DH_
    fp

    asDHP :: DH -> DHP
    asDHP :: DH -> DHP
    asDHP (DH ForeignPtr DH_
    fp) = ForeignPtr DH_ -> DHP
    DHP ForeignPtr DH_
    fp

    foreign import capi "openssl/dh.h DH_free"
      _DH_free :: Ptr DH_ -> IO ()