Next Previous Contents

2. Usage of C->Haskell

Let's have a brief look at how to call the tool and how to use the generated interfaces.

2.1 Usage of c2hs

C->Haskell is implemented by the executable c2hs. The simplest form of usage is

c2hs lib.h Lib.chs

where lib.h is the header file and Lib.chs the Haskell binding module, which define the C- and Haskell-side interface, respectively. If no errors occur, the result is a pure Haskell module Lib.hs, which implements the Haskell API of the library. It is possible to omit the C header file lib.h if instead appropriate CPP directives or inline C code is used in the Haskell binding module Lib.chs (see the section on CPP directives for details.) In any case, in addition to the Haskell module Lib.hs, a C header file Lib.h is generated. This header file should be provided to the Haskell compiler when compiling Lib.hs. Please ensure that no user-supplied header file is overwritten.

The executable c2hs has a couple more options:

Usage: c2hs [ option... ] [header-file] binding-file

  -C CPPOPTS  --cppopts=CPPOPTS   pass CPPOPTS to the C preprocessor         
  -c CPP      --cpp=CPP           use executable CPP to invoke C preprocessor
  -d TYPE     --dump=TYPE         dump internal information (for debugging)  
  -h, -?      --help              brief help (the present message)           
  -i INCLUDE  --include=INCLUDE   include paths for .chi files               
  -k          --keep              keep pre-processed C header                
  -o FILE     --output=FILE       output result to FILE (should end in .hs)  
  -v          --version           show version information                   
              --old-ffi[=OLDFFI]  use the FFI without `Ptr a'                

The header file must be a C header file matching the given binding file.
The dump TYPE can be
  trace   -- trace compiler phases
  genbind -- trace binding generation
  ctrav   -- trace C declaration traversal
  chs     -- dump the binding file (adds `.dump' to the name)

The most useful of these is probably --cppopts= (or -C). If the C header file needs any special options (like -D or -I) to go through the C pre-processor, here is the place to pass them. A call may look like this:

c2hs --cppopts='-I/some/obscure/dir -DEXTRA' lib.h Lib.chs

Do not forget the quotes if you have more than one option that you want to pass to the pre-processor.

Often, lib.h will not be in the current directory, but in one of the header file directories. C->Haskell leaves locating the header file to the standard C preprocessor, which usually looks in two places for the header: first, in the standard include directory of the used system, this is usually /usr/include and /usr/local/include; and second, it will look in every directory that is mentioned in a -IDIR option passed to the pre-processor via --cppopts.

If the compiled binding module contains import hooks, C->Haskell needs to find the .chi (C->Haskell interface files) produced while compiling the corresponding binding modules. By default, they will be searched for in the current working directory. If they are located elsewhere, the --include=INCLUDE option has to be used to indicate the location, where INCLUDE is a colon-separated list of directories. Multiple such options are admissible. Paths specified later are searched first.

2.2 Compilation of a Generated Haskell API

C->Haskell comes with a marshalling library, called C2HS, which is imported by virtually all library bindings. Consequently, you will have to tell the Haskell compiler where to find the interface files when you compile a generated interface and you have to tell the linker where to find the library archive of C2HS. To simplify this usually operating and compilation system-dependent process, C->Haskell comes with a simple configuration manager, in the form of the executable c2hs-conf. It can be used to inquire information for compilation and linking and pass that information on to the Haskell compiler. The call

c2hs-config --cflags

returns all flags that need to be given to the Haskell compiler for compilation and

c2hs-config --lib

returns all flags necessary for linking. Overall, you may want to use a call like the following to compile a generated library module with GHC:

ghc `c2hs-config --cflags` -#include\"Lib.h\" -c Lib.hs

The backquotes cause the shell to call c2hs-config and substitute the call by the flags returned. This, of course, also works in a makefile. Note how this call makes GHC include the C->Haskell-generated header file Lib.h into the generated code.

As an alternative, if you have registered C->Haskell's support libraries with GHC's package manager, you do not need to use c2hs-config, but instead, you can simply pass the option -package c2hs to GHC (both when compiling and when linking).

Furthermore, c2hs-config can also be used to locate the executable of the tool itself, by calling

c2hs-config --c2hs

This slightly simplifies configuration management of libraries generated by C->Haskell, as it is sufficient to know the location of c2hs-config to access all other components of C->Haskell.


Next Previous Contents