Let's have a brief look at how to call the tool and how to use the generated interfaces.
c2hs
C->Haskell is implemented by the executable c2hs
. The simplest form
of usage is
c2hs
Lib.chs
where Lib.chs
is the Haskell binding module defining the Haskell
interface to a C library together with the required marshalling code. If
C->Haskell is invoked in this manner, the binding module must contain a cpp
#include
directive to determine the C-side interface of the library.
Alternatively, a C header file can be specified on the command line, as in
c2hs
lib.h
Lib.chs
However, the latter option is only preserved for backwards compatibility and
not recommended. If no errors occur, C->Haskell generates three files: (1)
a pure Haskell module Lib.hs
, which implements the Haskell API of
the library, (2) a C header file Lib.h
which some Haskell systems
need to compile the generated Haskell code, and (3) a C->Haskell interface
file Lib.chi
that is used by other binding modules that import
Lib.hs
using an import hook (see
the section on import hooks for details).
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)
-t PATH --output-dir=PATH place generated files in PATH
-v --version show version information
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.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.
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.