Calling Haskell from C using GreenCard
Let's say you are working on a software project where different components of the system are written in different languages. Now one of your colleagues asks whether she can use your component (written as a Haskell library) from her component (written in C) for testing.
In this scenario, the controlling part of the application is in C, but it should be able to call out to Haskell from time to time, to perform some part of the computation. How can it be done?
We provide the necessary hooks in both C and Haskell. In essence, although C is supposedly in control, the program must start in Haskell (to initialise the heap and other runtime structures), before passing control over completely to C. Also, the initialisation phase must include a stage where C is given some handles on the Haskell functions it will later apply and evaluate.
The Haskell side is easy - just use GreenCard and pass functions across the boundary as stable pointers. For example:
module Main where %fun registerFn :: Int -> String -> a -> IO () %call (int arity) (string name) (stable fn) %fun handOver :: () -> IO () main = registerFn 2 "plus" ((+)::Int->Int->Int) >> registerFn 1 "mult5" ((5*)::Int->Int) >> handOver ()
The C side is also pretty straightforward. You need to write an appropriate implementation of registerFn which stores the Haskell values for later use. All Haskell stable pointers (whether functions or data) have a uniform representation as far as C is concerned: they are of type HaskellRef, which in practice should be treated as an abstract datatype. The C header file usr/local/lib/nhc98/greencard.h includes all the other facilities that are needed to deal with HaskellRefs - to build application closures and evaluate them, and to turn ordinary C values into HaskellRefs and vice versa.
----greencard.h---- typedef ... HaskellRef; extern HaskellRef buildClosure (int, HaskellRef*); extern void eval (HaskellRef); extern HaskellRef makeInt (int); extern int unmakeInt (HaskellRef); extern HaskellRef makeBool (int); extern int unmakeBool (HaskellRef); extern HaskellRef makeChar (char); extern char unmakeChar (HaskellRef);
Note the following points:
The latest updates to these pages are available on the WWW from http://www.haskell.org/nhc98/