{-# LANGUAGE CPP #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Language.C.Inline.FunPtr
( mkFunPtr
, mkFunPtrFromName
, peekFunPtr
, uniqueFfiImportName
) where
import Foreign.Ptr (FunPtr)
import qualified Language.Haskell.TH as TH
import qualified Language.Haskell.TH.Syntax as TH
mkFunPtr :: TH.TypeQ -> TH.ExpQ
mkFunPtr hsTy = do
ffiImportName <- uniqueFfiImportName
dec <- TH.forImpD TH.CCall TH.Safe "wrapper" ffiImportName [t| $(hsTy) -> IO (FunPtr $(hsTy)) |]
TH.addTopDecls [dec]
TH.varE ffiImportName
mkFunPtrFromName :: TH.Name -> TH.ExpQ
mkFunPtrFromName name = do
i <- TH.reify name
case i of
#if MIN_VERSION_template_haskell(2,11,0)
TH.VarI _ ty _ -> [| $(mkFunPtr (return ty)) $(TH.varE name) |]
#else
TH.VarI _ ty _ _ -> [| $(mkFunPtr (return ty)) $(TH.varE name) |]
#endif
_ -> fail "mkFunPtrFromName: expecting a variable as argument."
peekFunPtr :: TH.TypeQ -> TH.ExpQ
peekFunPtr hsTy = do
ffiImportName <- uniqueFfiImportName
dec <- TH.forImpD TH.CCall TH.Safe "dynamic" ffiImportName [t| FunPtr $(hsTy) -> $(hsTy) |]
TH.addTopDecls [dec]
TH.varE ffiImportName
uniqueFfiImportName :: TH.Q TH.Name
uniqueFfiImportName = TH.newName . show =<< TH.newName "inline_c_ffi"