hs-bindgen-1.0.0.0: src-internal/HsBindgen/Backend/Hs/CallConv.hs
-- | Calling conventions
--
-- Intended for unqualified import.
module HsBindgen.Backend.Hs.CallConv (
CWrapper(..)
, getCWrappersSource
, CallConv(..)
, ImportStyle(..)
, capiModule
) where
import GHC.Generics (Generic)
import HsBindgen.Backend.Runtime qualified as Runtime
import HsBindgen.IR.C qualified as C
import HsBindgen.Language.Haskell qualified as Hs
{-------------------------------------------------------------------------------
Definition
-------------------------------------------------------------------------------}
-- | The 'CallConvUserlandCapi' requires a wrapper on the C side with a
-- corresponding import.
newtype CWrapper = CWrapper {
definition :: String
}
deriving (Show, Generic)
-- | Source of the C translation unit containing the wrappers
--
-- The wrappers are preceded by the /whole/ root header, verbatim and in order,
-- reproducing the environment in which the declarations were parsed, including
-- the interleaving of @#define@s and @#include@s.
--
-- Duplicate @#include@s are preserved deliberately: re-inclusion at a different
-- point in the sequence is meaningful (X-macro headers). A header that cannot
-- tolerate double inclusion fails the root header parse in the binding
-- generation stage.
--
-- We emit nothing when there are no wrappers, so that a module without wrappers
-- does not gain a C translation unit.
getCWrappersSource :: [C.RootDirective C.HashIncludeArg] -> [CWrapper] -> String
getCWrappersSource _ [] = ""
getCWrappersSource directives wrappers =
C.renderRootDirectives directives ++ concatMap (.definition) wrappers
data CallConv =
-- | Our default calling convention: userland CAPI
--
-- There is no need to import the C header into the Haskell source file in
-- this case (the C header is only used by the wrapper on the C side).
--
-- We directly attach the C-side wrappers.
CallConvUserlandCapi CWrapper
-- | The standard GHC @capi@ calling convention
--
-- Although the @capi@ calling convention technically supports by-reference
-- imports, it does not actually do anything different than @ccall@ in this
-- case, and ignores the C header. For this reason we only support @ccall@
-- here.
--
-- NOTE: At the moment, we do not use the standard @capi@ calling
-- convention. We used it for symbol imports, but now also create wrappers
-- for those to work around bugs on Windows. We decided to leave the
-- constructor in, in case we need it in the future.
| CallConvGhcCapi FilePath
-- | The standard GHC \"ccall\" calling convention
| CallConvGhcCCall ImportStyle
deriving stock (Generic, Show)
data ImportStyle =
-- | Regular import
ImportAsValue
-- | @foreign import capi safe "header.h &foo" foo :: Ptr ..
| ImportAsPtr
deriving stock (Generic, Show)
-- | Module providing the userland CAPI support code.
capiModule :: Hs.ModuleName
capiModule = Runtime.moduleName Runtime.CAPI