Next Previous Contents

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 Mapping of Haskell types to C typess defines the mapping between Haskell and C types.


Haskell type
C type requirement range (7)
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) (6)
Double HsDouble floating point of unspec. size (5) (6)
-- (6)
-->Addr HsAddr void* (8)
ForeignObj HsForeignObj void* (9)
StablePtr HsStablePtr void* (10)
Mapping of Haskell types to C types

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. Floating-point limits are a little bit more complicated, so preprocessor macros mirroring ISO C's float.h are provided:
          HS_{FLOAT,DOUBLE}_RADIX
          HS_{FLOAT,DOUBLE}_ROUNDS
          HS_{FLOAT,DOUBLE}_EPSILON
          HS_{FLOAT,DOUBLE}_DIG
          HS_{FLOAT,DOUBLE}_MANT_DIG
          HS_{FLOAT,DOUBLE}_MIN
          HS_{FLOAT,DOUBLE}_MIN_EXP
          HS_{FLOAT,DOUBLE}_MIN_10_EXP
          HS_{FLOAT,DOUBLE}_MAX
          HS_{FLOAT,DOUBLE}_MAX_EXP
          HS_{FLOAT,DOUBLE}_MAX_10_EXP
    
  7. The bounds are preprocessor macros, so they can be used in #if and for array bounds.
  8. 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).
  9. 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.
  10. 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.
  11. To avoid name clashes, identifiers starting with Hs and macros starting with HS_ are reserved for the FFI.
  12. GHC only: The GHC specific types ByteArray and MutableByteArray both map to char*.


Next Previous Contents