inline-c- Write Haskell source files including C code inline. No FFI required.

Safe HaskellNone




A Context is used to define the capabilities of the Template Haskell code that handles the inline C code. See the documentation of the data type for more details.

In practice, a Context will have to be defined for each library that defines new C types, to allow the TemplateHaskell code to interpret said types correctly.



type TypesTable = Map TypeSpecifier TypeQ Source

A mapping from TypeSpecifiers to Haskell types. Needed both to parse C types, and to convert them to Haskell types.

data Purity Source

A data type to indicate whether the user requested pure or IO function from Haskell




convertType :: Purity -> TypesTable -> Type -> Q (Maybe Type) Source

Given a Context, it uses its ctxTypesTable to convert arbitrary C types.

type CArray = Ptr Source

An alias for Ptr.


data AntiQuoter a Source

Specifies how to parse and process an antiquotation in the C code.

All antiquotations (apart from plain variable capture) have syntax


Where XXX is the name of the antiquoter and YYY is something parseable by the respective aqParser.




aqParser :: forall m. CParser m => m (String, Type, a)

Parses the body of the antiquotation, returning a hint for the name to assign to the variable that will replace the anti-quotation, the type of said variable, and some arbitrary data which will then be fed to aqMarshaller.

aqMarshaller :: Purity -> TypesTable -> Type -> a -> Q (Type, Exp)

Takes the requested purity, the current TypesTable, and the type and the body returned by aqParser.

Returns the Haskell type for the parameter, and the Haskell expression that will be passed in as the parameter.

If the the type returned is ty, the Exp must have type forall a. (ty -> IO a) -> IO a. This allows to do resource handling when preparing C values.

Care must be taken regarding Purity. Specifically, the generated IO computation must be idempotent to guarantee its safety when used in pure code. We cannot prevent the IO computation from being inlined, hence potentially duplicated. If non-idempotent marshallers are required (e.g. if an update to some global state is needed), it is best to throw an error when Purity is Pure (for example "you cannot use context X with pure"), which will show up at compile time.

type AntiQuoterId = String Source

An identifier for a AntiQuoter.

data SomeAntiQuoter Source

Existential wrapper around AntiQuoter.


forall a . (Eq a, Typeable a) => SomeAntiQuoter (AntiQuoter a) 


data Context Source

A Context stores various information needed to produce the files with the C code derived from the inline C snippets.

Contexts can be composed with their Monoid instance, where mappend is right-biased -- in mappend x y y will take precedence over x.




ctxTypesTable :: TypesTable

Needed to convert C types to Haskell types.

ctxAntiQuoters :: AntiQuoters

Needed to parse and process antiquotations.

ctxFileExtension :: Maybe String

Will determine the extension of the file containing the inline C snippets.

ctxOutput :: Maybe (String -> String)

This function is used to post-process the functions generated from the C snippets. Currently just used to specify C linkage when generating C++ code.


baseCtx :: Context Source

Context useful to work with vanilla C. Used by default.

ctxTypesTable: converts C basic types to their counterparts in Foreign.C.Types.

No ctxAntiQuoters.

funCtx :: Context Source

This Context includes a AntiQuoter that removes the need for explicitely creating FunPtrs, named "fun".

For example, we can capture function f of type CInt -> CInt -> IO CInt in C code using $fun:(int (*f)(int, int)).

When used in a pure embedding, the Haskell function will have to be pure too. Continuing the example above we'll have CInt -> CInt -> IO CInt.

Does not include the baseCtx, since most of the time it's going to be included as part of larger contexts.

vecCtx :: Context Source

This Context includes two AntiQuoters that allow to easily use Haskell vectors in C.

Specifically, the vec-len and vec-ptr will get the length and the pointer underlying mutable (IOVector) and immutable (Vector) storable vectors.

Note that if you use vecCtx to manipulate immutable vectors you must make sure that the vector is not modified in the C code.

To use vec-len, simply write $vec-len:x, where x is something of type IOVector a or Vector a, for some a. To use vec-ptr you need to specify the type of the pointer, e.g. $vec-len:(int *x) will work if x has type IOVector CInt.

class VecCtx a where Source

Type class used to implement the anti-quoters in vecCtx.

Associated Types

type VecCtxScalar a :: * Source


vecCtxLength :: a -> Int Source

vecCtxUnsafeWith :: a -> (Ptr (VecCtxScalar a) -> IO b) -> IO b Source


bsCtx :: Context Source

bsCtx serves exactly the same purpose as vecCtx, but only for ByteString. vec-ptr becomes bs-ptr, and vec-len becomes bs-len. You don't need to specify the type of the pointer in bs-ptr, it will always be unsigned char*.