A Haskell binding module may include arbitrary C pre-processor directives using the standard C syntax. The directives are used in two ways: Firstly, they are included in the C header file generated by C->Haskell in exactly the same order in which they appear in the binding module. Secondly, all conditional directives are honoured by C->Haskell in that all Haskell binding code in alternatives that are discarded by the C pre-processor are also discarded by C->Haskell. This latter feature is, for example, useful to maintain different bindings for multiple versions of the same C API in a single Haskell binding module.
In addition to C pre-processor directives, vanilla C code can be maintained in
a Haskell binding module by bracketing this C code with the pseudo directives
#c
and #endc
. Such inline C code is emitted into the C header
generated by C->Haskell at exactly the same position relative to CPP
directives as it occurs in the binding module. Pre-processor directives may
encompass the #include
directive, which can be used instead of specifying
a C header file as an argument to c2hs
. In particular, this enables the
simultaneous use of multiple header files without the need to provide a custom
header file that binds them together. If a header file lib.h
is
specified as an argument to c2hs
, the tool will emit the directive
#include"
lib.h"
into the generated C header before any other
CPP directive or inline C code.
As an artificial example of these features consider the following code:
#define VERSION 2
#if (VERSION == 1)
foo :: CInt -> CInt
foo = {#call pure fooC#}
#else
foo :: CInt -> CInt -> CInt
foo = {#call pure fooC#}
#endif
#c
int fooC (int, int);
#endc
One of two versions of the Haskell function foo
(having different arities)
is selected in dependence on the value of the CPP macro VERSION
, which in
this example is defined in the same file. In realistic code, VERSION
would be defined in the header file supplied with the C library that is made
accessible from Haskell by a binding module. The above code fragment also
includes one line of inline C code that declares a C prototype for fooC
.
Current limitation of the implementation: Inline C code can currently not contain any code blocks; i.e., only declarations as typically found in header files may be included.