The Binding Generator C->Haskell : Implementation of Haskell Binding Modules : CPP Directives and Inline C Code
Previous: Class Hooks
Next: Grammar Rules

2.12. CPP Directives and Inline C Code

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.


The Binding Generator C->Haskell : Implementation of Haskell Binding Modules : CPP Directives and Inline C Code
Previous: Class Hooks
Next: Grammar Rules