8.2. Calling foreign functions

To bind a Haskell variable name and type to an external function, we introduce a new construct: foreign import. It defines the type of a Haskell function together with the name of an external function that actually implements it. The syntax of foreign import construct is as follows:

  : ...
  | 'foreign' 'import' [callconv] [ext_fun] ['unsafe'] varid '::' prim_type

A foreign import declaration is only allowed as a toplevel declaration. It consists of two parts, one giving the Haskell type (prim_type), Haskell name (varid) and a flag indicating whether the primitive is unsafe, the other giving details of the name of the external function (ext_fun) and its calling interface (callconv.)

Giving a Haskell name and type to an external entry point is clearly an unsafe thing to do, as the external name will in most cases be untyped. The onus is on the programmer using foreign import to ensure that the Haskell type given correctly maps on to the type of the external function. Section 8.2.5 specifies the mapping from Haskell types to external types.

8.2.1. Giving the external function a Haskell name

The external function has to be given a Haskell name. The name must be a Haskell varid, so the language rules regarding variable names must be followed, i.e., it must start with a lower case letter followed by a sequence of alphanumeric (`in the Unicode sense') characters or '. [1]

varid : small ( small | large | udigit | ' )*

8.2.2. Naming the external function

The name of the external function consists of two parts, one specifying its location, the other its name:

ext_fun  : ext_loc ext_name
         | ext_name

ext_name : string
ext_loc  : string

For example,

foreign import stdcall "Advapi32" "RegCloseKey" regCloseKey :: Addr -> IO ()

states that the external function named RegCloseKey at location Advapi32 should be bound to the Haskell name regCloseKey. For a Win32 Haskell implementation that supports the loading of DLLs on-the-fly, this declaration will most likely cause the run-time system to load the Advapi32.dll DLL before looking up the function RegCloseKey() therein to get at the function pointer to use when invoking regCloseKey.

Compiled implementations may do something completely different, i.e., mangle "RegCloseKey" to convert it into an archive/import library symbol, that's assumed to be in scope when linking. The details of which are platform (and compiler command-line) dependent.

If the location part is left out, the name of the external function specifies a symbol that is assumed to be in scope when linking.

The location part can either contain an absolute `address' (i.e., path) of the archive/DLL, or just its name, leaving it up to the underlying system (system meaning both RTS/compiler and OS) to resolve the name to its real location.

An implementation is expected to be able to intelligently transform the ext_loc location to fit platform-specific practices for naming dynamic libraries. For instance, given the declaration

foreign import "Foo" "foo" foo :: Int -> Int -> IO ()

an implementation should map Foo to "Foo.dll" on a Win32 platform, and libFoo.so on ELF platforms. If the lookup of the dynamic library with this transformed location name should fail, the implementation should then attempt to use the original name before eventually giving up. As part of their documentation, implementations of foreign import should specify the exact details of how ext_locs are transformed and resolved, including the list of directories searched (and the order in which they are.)

In the case the Haskell name of the imported function is identical to the external name, the ext_fun can be omitted. i.e.,

foreign import sin :: Double -> IO Double

is identical to

foreign import "sin" sin :: Double -> IO Double

8.2.3. Calling conventions

The number of calling conventions supported is fixed:

callconv : ccall | stdcall


The 'default' calling convention on a platform, i.e., the one used to do (C) function calls.

In the case of x86 platforms, the caller pushes function arguments from right to left on the C stack before calling. The caller is responsible for popping the arguments off of the C stack on return.


A Win32 specific calling convention. The same as ccall, except that the callee cleans up the C stack before returning. [2]

Some remarks:

8.2.4. External function types

The range of types that can be passed as arguments to an external function is restricted (as are the range of results coming back):

prim_type : IO prim_result
          | prim_result
          | prim_arg '->' prim_type

Section defines prim_result; Section defines prim_arg. Argument types

The external function expects zero or more arguments. The set of legal argument types is restricted to the following set:

prim_arg : ext_ty | new_ty | ForeignObj

new_ty : a Haskell newtype of a prim_arg.

ext_ty : int_ty   | word_ty | float_ty
       | Addr     | Char    | StablePtr a
       | Bool

int_ty       : Int   | Int8   | Int16   | Int32 | Int64
word_ty      : Word8 | Word16 | Word32  | Word64
float_ty     : Float | Double

  • ext_ty represent the set of basic types supported by C-like languages, although the numeric types are explicitly sized. The stable pointer StablePtr type looks out of place in this list of C-like types, but it has a well-defined and simple C mapping, see Section 8.2.5 for details.

  • prim_arg represent the set of permissible argument types. In addition to ext_ty, ForeignObj is also included. The ForeignObj type represent values that are pointers to some external entity/object. It differs from the Addr type in that ForeignObjs are finalized, i.e., once the garbage collector determines that a ForeignObj is unreachable, it will invoke a finalising procedure attached to the ForeignObj to notify the outside world that we're through with using it.

  • Haskell newtypes that wrap up a prim_arg type can also be passed to external functions.

  • Haskell type synonyms for any of the above can also be used in foreign import declarations. Qualified names likewise, i.e. Word.Word32 is legal.

  • foreign import does not support the binding to external constants/variables. A foreign import declaration that takes no arguments represent a binding to a function with no arguments.

  • GHC only: GHC's implementation of the FFI provides two extensions:

    • Support for passing heap allocated byte arrays to an external function
      prim_type : ... 
                | prim_arg '->' prim_type
                | unsafe_arr_ty '->' prim_type
      unsafe_arr_ty : ByteArray a
                    | MutableByteArray i s a
      GHC's ByteArray and MutableByteArray primitive types are (im)mutable chunks of memory allocated on the Haskell heap, and pointers to these can be passed to foreign imported external functions provided they are marked as unsafe. Since it is inherently unsafe to hand out references to objects in the Haskell heap if the external call may cause a garbage collection to happen, you have to annotate the foreign import declaration with the attribute unsafe. By doing so, the user explicitly states that the external function won't provoke a garbage collection, so passing out heap references to the external function is allright.

    • Another GHC extension is the support for unboxed types:
      prim_arg : ...  | unboxed_h_ty
      ext_ty   : .... | unboxed_ext_ty
      unboxed_ext_ty : Int#   | Word#    | Char#
                     | Float# | Double#  | Addr# 
      	       | StablePtr# a
      unboxed_h_ty : MutableByteArray# | ForeignObj#
                   | ByteArray#
      Clearly, if you want to be portable across Haskell systems, using system-specific extensions such as this is not advisable; avoid using them if you can. (Support for using unboxed types might be withdrawn sometime in the future.) Result type

An external function is permitted to return the following range of types:

prim_result : ext_ty | new_ext_ty | ()

new_ext_ty : a Haskell newtype of an ext_ty.

where () represents void / no result.

  • External functions cannot raise exceptions (IO exceptions or non-IO ones.) It is the responsibility of the foreign import user to layer any error handling on top of an external function.

  • Only external types (ext_ty) can be passed back, i.e., returning ForeignObjs is not supported/allowed.

  • Haskell newtypes that wrap up ext_ty are also permitted.

8.2.5. Type mapping

For the FFI to be of any practical use, the properties and sizes of the various types that can be communicated between the Haskell world and the outside, needs to be precisely defined. We do this by presenting a mapping to C, as it is commonly used and most other languages define a mapping to it. Table Table 8-1 defines the mapping between Haskell and C types.

Table 8-1. Mapping of Haskell types to C types

Haskell type C type requirement range (9)   
Char HsChar unspec. integral type HS_CHAR_MIN .. HS_CHAR_MAX
Int HsInt signed integral of unspec. size(4) HS_INT_MIN .. HS_INT_MAX
Int8 (2) HsInt8 8 bit signed integral HS_INT8_MIN .. HS_INT8_MAX
Int16 (2) HsInt16 16 bit signed integral HS_INT16_MIN .. HS_INT16_MAX
Int32 (2) HsInt32 32 bit signed integral HS_INT32_MIN .. HS_INT32_MAX
Int64 (2,3) HsInt64 64 bit signed integral (3) HS_INT64_MIN .. HS_INT64_MAX
Word8 (2) HsWord8 8 bit unsigned integral 0 .. HS_WORD8_MAX
Word16 (2) HsWord16 16 bit unsigned integral 0 .. HS_WORD16_MAX
Word32 (2) HsWord32 32 bit unsigned integral 0 .. HS_WORD32_MAX
Word64 (2,3) HsWord64 64 bit unsigned integral (3) 0 .. HS_WORD64_MAX
Float HsFloat floating point of unspec. size (5) (10)
Double HsDouble floating point of unspec. size (5) (10)
Bool HsBool unspec. integral type (11)
Addr HsAddr void* (6)  
ForeignObj HsForeignObj void* (7)  
StablePtr HsStablePtr void* (8)  

Some remarks:

  1. A Haskell system that implements the FFI will supply a header file HsFFI.h that includes target platform specific definitions for the above types and values.

  2. The sized numeric types Hs{Int,Word}{8,16,32,64} have a 1-1 mapping to ISO C 99's {,u}int{8,16,32,64}_t. For systems that doesn't support this revision of ISO C, a best-fit mapping onto the supported C types is provided.

  3. An implementation which does not support 64 bit integral types on the C side should implement Hs{Int,Word}64 as a struct. In this case the bounds HS_INT64_{MIN,MAX} and HS_WORD64_MAX are undefined.

  4. A valid Haskell representation of Int has to be equal to or wider than 30 bits. The HsInt synonym is guaranteed to map onto a C type that satisifies Haskell's requirement for Int.

  5. It is guaranteed that Hs{Float,Double} are one of C's floating-point types float/double/long double.

  6. It is guaranteed that HsAddr is of the same size as void*, so any other pointer type can be converted to and from HsAddr without any loss of information (K&R, Appendix A6.8).

  7. Foreign objects are handled like Addr by the FFI, so there is again the guarantee that HsForeignObj is the same as void*. The separate name is meant as a reminder that there is a finalizer attached to the object pointed to.

  8. Stable pointers are passed as addresses by the FFI, but this is only because a void* is used as a generic container in most APIs, not because they are real addresses. To make this special case clear, a separate C type is used here.

  9. The bounds are preprocessor macros, so they can be used in #if and for array bounds.

  10. Floating-point limits are a little bit more complicated, so preprocessor macros mirroring ISO C's float.h are provided:

  11. It is guaranteed that Haskell's False/True map to C's 0/1, respectively, and vice versa. The mapping of any other integral value to Bool is left unspecified.

  12. To avoid name clashes, identifiers starting with Hs and macros starting with HS_ are reserved for the FFI.

  13. GHC only: The GHC specific types ByteArray and MutableByteArray both map to char*.

8.2.6. Some foreign import wrinkles



Notice that with Haskell 98, underscore ('_') is included in the character class small.


The stdcall is a Microsoft Win32 specific wrinkle; it's used throughout the Win32 API, for instance. On platforms where stdcall isn't meaningful, it should be treated as being equal to ccall.