GreenCard for nhc98
GreenCard is a preprocessor for Haskell which allows Haskell
functions to call C. (For the really brave, nhc98 also has the
ability to call Haskell code from C
using GreenCard to set up the interface.)
A paper (now superseded, see below) published in
the Haskell Workshop 97 proceedings describes the design goals, input
language, and translation mechanism. GreenCard was supposed
to be standard across implementations of Haskell - however the
Hugs/ghc version has now diverged somewhat.
A new, more flexible but lower-level, primitive FFI is now common
to Hugs/ghc and nhc98, and it provides a
greater degree of cross-compiler portability than GreenCard.
However, GreenCard is still useful for many small tasks, and
you may find it is just the right tool for your particular application.
Since the Haskell Workshop paper, several improvements have been
made to the input language and DIS macros. GreenCard
for nhc98 follows the design agreed with the Glasgow and
Hugs implementors (although the Glasgow implementation does not!).
Here is the best extant description of
GreenCard closely matching the nhc98 version.
There are just a few differences specific to the nhc98 version
of the tool.
- Some features are not implemented.
- %fail is currently ignored
silently; %const generates a warning and terminates processing;
you cannot yet use named fields (sometimes known as records) in DIS
- Import clause needed.
- The code generated by GreenCard uses certain library
functions, which may not be visible in the source submitted to
GreenCard. To make things easier, we have collected these
functions together into a single library module, which should always
be imported when you use GreenCard. Simply add the line
to your source file. GreenCard cannot add this line for
- Filename conventions.
- Source files containing GreenCard directives should have a
.gc extension. Both nhc98 and hmake
recognise the .gc extension and call GreenCard
automatically. When GreenCard is run on a file
Module.gc it generates two new files Module_.hs
and Module_.c which are processed separately by
nhc98 proper and gcc. The end result however is
still a single object file called Module.o. (We thought it
would be useful to expose the generated files to the user, since
any compilation errors will refer to these rather than to the
original source (although of course the error must be fixed in the
original .gc file)).
- Calling Haskell from C.
- The Haskell Workshop paper said that "in practice there is zero demand"
for calling Haskell from C. We disagree. Using "stable pointers"
however, it is possible to go some distance towards providing such a
facility. See the document
file $NHC98DIR/lib/greencard.h for details.
(Note: the newer primitive FFI makes this
very much easier - we recommend you use it instead.)
- DIS variable scope.
- The original paper said: "All the C variables bound in the
%call statement, and all those bound in declarations at the start of
the body scope over all the result-marshalling statements (%result and
%fail)". However, it did not say anything about the scope of
variables bound by a %result statement. We say that variables bound
in a %result statement are always declared implicitly and scope over
the whole body. For example, from the paper:
%fun foo :: (Age,Age) -> Age
%call (Age (int x), Age (int y))
%code r = foo(x,y);
%result (Age (int r))
This example is correct, and indicates that the three variables x y and r
are all declared as "int"s prior to the %code body, and scope over the
%fun f :: This -> This
%call (MkThis (int p) (float q, float r))
%code int a,b,c;
% f( p, q, r, &a, &b, &c);
%result (this a b c)
But this example is incorrect, because the user's definitions of a b and c
conflict with the automatic definition from the %result statement. (The
variables b and c are "float"s, but the user has tried to declare them as
The latest updates to these pages are available on the WWW from
York Functional Programming Group