Primitive FFI in nhc98
The nhc98 compiler contains an implementation of the
standard foreign function interface that is also available
in Hugs and ghc. The most recent released version
of nhc98 implements the latest standard syntax for foreign
function declarations, as specified at:
The FFI standard specifies both the basic mechanism as a language
extension, and a layer of libraries. The libraries contain many useful
datatypes and access functions, for instance to manage memory storage
in the foreign language. nhc98's implementation includes two versions
of these libraries: nhc98's internal FFI
library, and the standard
portable Foreign libraries. The latter collection departs from
the official standard only in the use of the hierarchical module
namespace instead of the official flat namespace.
- Supported calling conventions are: ccall, noproto,
and cast. (The latter two are non-standard, see below.)
Unsupported calling conventions are: stdcall, jvm,
- foreign import "wrapper" is not yet supported.
- The annotation unsafe has no special meaning in nhc98;
it is purely a speed optimisation for ghc.
- A foreign export specification is treated as the actual
type signature for the exported function. You are not allowed a
second (possibly more general) type signature.
- Hence, you cannot foreign export any function that
requires a class dictionary.
- Two non-standard calling conventions are provided.
cast indicates that an arity-1 foreign import is only being
used for its C type-cast, and hence eliminates some runtime overheads.
foreign import cast floatToDouble :: Float -> Double
The calling convention noproto is essentially the same as
ccall but tells the compiler not to generate a C function
prototype for the external function. For example,
foreign import sin noproto :: Float -> Float
eliminates the normal generation of
extern float sin (float);
for occasions when such a declaration might conflict with an external
declaration. (Note, if you mention a header file in the foreign entity
description, this has the same effect as noproto - i.e. the header file
declaration is used in preference to generating a prototype.)
- The set of primitive types allowed across the FFI is slightly
larger in nhc98 than the standard allowed set: we
allow PackedString to be passed - these are genuine
null-terminated C-style strings. Used as a result type, the
string is copied into the Haskell heap (allowing the original
pointer to be freed safely); used as an argument type, a pointer
to the heap-allocated string is passed to C (i.e. do not free
it!). However, we recommend you use the standard type
Foreign.C.String instead - it is more portable.
- Additionally, we allow any non-primitive datatype to be passed
across the FFI (but give a Warning for each one) as a heap
pointer. This feature should only be used by serious implementers,
because any foreign code manipulating non-primitive data must use
nhc98's internal heap format.
- In a foreign import specification, the specification of a
C header file or library in the "external entity" string was
previously ignored. nhc98 now generates #include
for these header files. Where a header file is specified, the
compiler does not generate its own prototype for the foreign function,
as if the 'noproto' calling convention had been used.
- foreign import "dynamic" is now fully supported.
The latest updates to these pages are available on the WWW from
This page last modified: 16th June 2003
York Functional Programming Group