clr-host-0.2.0: src/Clr/Host/Delegate.hs
module Clr.Host.Delegate where
import Clr.Host.BStr
import Clr.Host.GCHandle
import Clr.Host.DriverEntryPoints
import Clr.Marshal
import Data.Kind
import Foreign.Ptr
-- | @'getDelegateConstructorStub' dt wrapper@ returns an action that, given a
-- function, will return a reference to a .NET delegate object that calls the
-- provided function. The delegate constructed will be of the type @dt@.
-- The function @wrapper@ will be called in order to wrap the given function
-- as a function pointer for passing into .NET.
getDelegateConstructorStub :: String -> (f -> IO (FunPtr f)) -> IO (f -> IO (GCHandle t))
getDelegateConstructorStub delegateTypeName wrapper = do
-- Obtain a function pointer to a function that, when called with a
-- function pointer compatible with the given wrapper function, returns
-- a reference to a .NET delegate object that calls the function.
delegateConstructor <- marshal delegateTypeName $
\delegateTypeName' -> getDelegateConstructorStubRaw >>= \x-> x delegateTypeName'
-- Returns a function that accepts a function, 'f' implementing the
-- delegate, converts 'f' to a function pointer, and then wraps it
-- up as a .NET delegate.
return $ \f -> do
fFunPtr <- wrapper f
(makeDelegateConstructor delegateConstructor) fFunPtr
getDelegateConstructorStubRaw :: IO (GetDelegateConstructorStubDelegate f t)
getDelegateConstructorStubRaw = unsafeGetPointerToMethod "GetDelegateConstructorStub" >>= return . makeGetDelegateConstructorStubDelegate
type GetDelegateConstructorStubDelegate f t = BStr -> IO (FunPtr (DelegateConstructor f t))
foreign import ccall "dynamic" makeGetDelegateConstructorStubDelegate :: FunPtr (GetDelegateConstructorStubDelegate f t) -> (GetDelegateConstructorStubDelegate f t)
type DelegateConstructor f t = FunPtr f -> IO (GCHandle t)
foreign import ccall "dynamic" makeDelegateConstructor :: FunPtr (DelegateConstructor f t) -> (DelegateConstructor f t)