Primitive FFI in nhc98


The nhc98 compiler contains an implementation of the standard foreign function interface that is also available in Hugs and ghc. Version 1.16 implements the latest standard syntax for foreign function declarations, as specified at: http://www.cse.unsw.edu.au/~chak/haskell/ffi/

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.


Compliance notes

  • Supported calling conventions are: ccall, noproto, and cast. Unsupported calling conventions are: stdcall, jvm, dotnet, cplusplus.
  • In a foreign import specification, the specification of a C header file or library in the "external entity" string is currently ignored. nhc98 does not use header files for checking prototypes, and it does not yet support dynamic library linking.
  • foreign import "wrapper" and foreign import "dynamic" are not yet supported.
  • The annotation unsafe is ignored and treated as if it were safe; it is purely a speed optimisation for ghc.
  • The annotation threadsafe has no special meaning in nhc98, since it does not implement the concurrent threads extension.
  • 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. For example,
      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 a #include'd declaration.
  • 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.
  • 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.



The latest updates to these pages are available on the WWW from http://www.haskell.org/nhc98/

This page last modified: 20 January 2003
York Functional Programming Group