6 C-Specific Marshalling

6.1 CForeign

The module CForeign combines the interfaces of all modules providing C-specific marshalling support. The modules are CTypes, CString, and CError.





C symbol Haskell symbolConstraint on concrete C type






HsChar Char integral type



HsInt Int signed integral type, > 30 bit



HsInt8 Int8 signed integral type, 8 bit; int8_t if available



HsInt16 Int16 signed integral type, 16 bit; int16_t if available



HsInt32 Int32 signed integral type, 32 bit; int32_t if available



HsInt64 Int64 signed integral type, 64 bit; int64_t if available



HsWord8 Word8 unsigned integral type, 8 bit; uint8_t if available



HsWord16 Word16 unsigned integral type, 16 bit; uint16_t if available



HsWord32 Word32 unsigned integral type, 32 bit; uint32_t if available



HsWord64 Word64 unsigned integral type, 64 bit; uint64_t if available



HsFloat Float floating point type



HsDouble Double floating point type



HsBool Bool int



HsPtr Ptr a (void *)



HsFunPtr FunPtr a (void (*)(void))



HsStablePtrStablePtr a (void *)




Table 2: C Interface to Basic Haskell Types





CPP symbol Haskell value

Description







HS_CHAR_MIN minBound :: Char




HS_CHAR_MAX maxBound :: Char




HS_INT_MIN minBound :: Int




HS_INT_MAX maxBound :: Int




HS_INT8_MIN minBound :: Int8




HS_INT8_MAX maxBound :: Int8




HS_INT16_MIN minBound :: Int16




HS_INT16_MAX maxBound :: Int16




HS_INT32_MIN minBound :: Int32




HS_INT32_MAX maxBound :: Int32




HS_INT64_MIN minBound :: Int64




HS_INT64_MAX maxBound :: Int64




HS_WORD8_MAX maxBound :: Word8




HS_WORD16_MAX maxBound :: Word16




HS_WORD32_MAX maxBound :: Word32




HS_WORD64_MAX maxBound :: Word64




HS_FLOAT_RADIX floatRadix :: Float




HS_FLOAT_ROUND n/a

rounding style as per [3]




HS_FLOAT_EPSILON n/a

difference between 1 and the least value greater than 1 as per [3]




HS_DOUBLE_EPSILON n/a

(as above)




HS_FLOAT_DIG n/a

number of decimal digits as per [3]




HS_DOUBLE_DIG n/a

(as above)




HS_FLOAT_MANT_DIG floatDigits :: Float




HS_DOUBLE_MANT_DIG floatDigits :: Double




HS_FLOAT_MIN n/a

minimum floating point number as per [3]




HS_DOUBLE_MIN n/a

(as above)




HS_FLOAT_MIN_EXP fst . floatRange :: Float




HS_DOUBLE_MIN_EXP fst . floatRange :: Double




HS_FLOAT_MIN_10_EXP n/a

minimum decimal exponent as per [3]




HS_DOUBLE_MIN_10_EXPn/a

(as above)




HS_FLOAT_MAX n/a

maximum floating point number as per [3]




HS_DOUBLE_MAX n/a

(as above)




HS_FLOAT_MAX_EXP snd . floatRange :: Float




HS_DOUBLE_MAX_EXP snd . floatRange :: Double




HS_FLOAT_MAX_10_EXP n/a

maximum decimal exponent as per [3]




HS_DOUBLE_MAX_10_EXPn/a

(as above)




HS_BOOL_FALSE False




HS_BOOL_TRUE True





Table 3: C Interface to Range and Precision of Basic Types

Every Haskell system that implements the FFI needs to provide a C header file named HsFFI.h that defines the C symbols listed in Tables 2 and 3. Table 2 table lists symbols that represent types together with the Haskell type that they represent and any constraints that are placed on the concrete C types that implement these symbols. When a C type HsT represents a Haskell type T, the occurrence of T in a foreign function declaration should be matched by HsT in the corresponding C function prototype. Indeed, where the Haskell system translates Haskell to C code that invokes foreign imported C routines, such prototypes need to be provided and included via the header that can be specified in external entity strings for foreign C functions (cf. Section 4.1); otherwise, the system behaviour is undefined. It is guaranteed that the Haskell value nullPtr is mapped to (HsPtr) NULL in C and nullFunPtr is mapped to (HsFunPtr) NULL and vice versa.

Table 3 contains symbols characterising the range and precision of the types from Table 2. Where available, the table states the corresponding Haskell values. All C symbols, with the exception of HS_FLOAT_ROUND are constants that are suitable for use in #if preprocessing directives. Note that there is only one rounding style (HS_FLOAT_ROUND) and one radix (HS_FLOAT_RADIX), as this is all that is supported by ISO C [3].

Moreover, an implementation that does not support 64 bit integral types on the C side should implement HsInt64 and HsWord64 as a structure. In this case, the bounds HS_INT64_MIN, HS_INT64_MAX, and HS_WORD64_MAX are undefined.

In addition, to the symbols from Table 2 and 3, the header HsFFI.h must also contain the following prototypes:

void hs_init     (int *argc, char **argv[]);  
void hs_exit     (void);  
void hs_set_argv (int argc, char *argv[]);  
 
void hs_perform_gc (void);  
 
void hs_free_stable_ptr (HsStablePtr sp);  
void hs_free_fun_ptr    (HsFunPtr fp);

These routines are useful for mixed language programs, where the main application is implemented in a foreign language that accesses routines implemented in Haskell. The function hs_init() initialises the Haskell system and provides it with the available command line arguments. Upon return, the arguments solely intended for the Haskell runtime system are removed (i.e., the values that argc and argv point to may have changed). This function must be called during program startup before any Haskell function is invoked; otherwise, the system behaviour is undefined. Conversely, the Haskell system is deinitialised by a call to hs_exit(). Multiple invocations of hs_init() are permitted, provided that they are followed by an equal number of calls to hs_exit() and that the first call to hs_exit() is after the last call to hs_init(). In addition to nested calls to hs_init(), the Haskell system may be de-initialised with hs_exit() and be re-initialised with hs_init() at a later point in time. This ensures that repeated initialisation due to multiple libraries being implemented in Haskell is covered.

The Haskell system will ignore the command line arguments passed to the second and any following calls to hs_init(). Moreover, hs_init() may be called with NULL for both argc and argv, signalling the absence of command line arguments.

The function hs_set_argv() sets the values returned by the functions getProgName and getArgs of the module System defined in the Haskell 98 Library Report. This function may only be invoked after hs_init(). Moreover, if hs_set_argv() is called at all, this call must precede the first invocation of getProgName and getArgs. Note that the separation of hs_init() and hs_set_argv() is essential in cases where in addition to the Haskell system other libraries that process command line arguments during initialisation are used.

The function hs_perform_gc() advises the Haskell storage manager to perform a garbage collection, where the storage manager makes an effort to releases all unreachable objects. This function must not be invoked from C functions that are imported unsafe into Haskell code nor may it be used from a finalizer.

Finally, hs_free_stable_ptr() and hs_free_fun_ptr() are the C counterparts of the Haskell functions freeStablePtr and freeHaskellFunPtr.

6.2 CTypes

The modules CTypes provide Haskell types that represent basic C types. They are needed to accurately represent C function prototypes, and so, to access C library interfaces in Haskell. The Haskell system is not required to represent those types exactly as C does, but the following guarantees are provided concerning a Haskell type CT representing a C type t:

All types exported by CTypes must be represented as newtypes of basic foreign types as defined in Section 3.2 and the export must be abstract.

The module CTypes provides the following integral types, including instances for Eq, Ord, Num, Read, Show, Enum, Storable, Bounded, Real, Integral, and Bits:




Haskell typeRepresented C type






CChar char



CSChar signed char



CUChar unsigned char



CShort short



CUShort unsigned short



CInt int



CUInt unsigned int



CLong long



CULong unsigned long



CLLong long long



CULLong unsigned long long



Moreover, it provides the following floating point types, including instances for Eq, Ord, Num, Read, Show, Enum, Storable, Real, Fractional, Floating, RealFrac, and RealFloat:




Haskell typeRepresented C type






CFloat float



CDouble double



CLDouble long double



The module provides the following integral types, including instances for Eq, Ord, Num, Read, Show, Enum, Storable, Bounded, Real, Integral, and Bits:




Haskell typeRepresented C type






CPtrdiff ptrdiff_t



CSize size_t



CWchar wchar_t



CSigAtomicsig_atomic_t



Moreover, it provides the following numeric types, including instances for Eq, Ord, Num, Read, Show, Enum, and Storable:




Haskell typeRepresented C type






CClock clock_t



CTime time_t



And finally, the following types, including instances for Eq and Storable, are provided:




Haskell typeRepresented C type






CFile FILE



CFpos fpos_t



CJmpBuf jmp_buf



6.3 CString

The module CString provides routines marshalling Haskell into C strings and vice versa. The marshalling converts each Haskell character, representing a Unicode code point, to one or more bytes in a manner that, by default, is determined by the current locale. As a consequence, no guarantees can be made about the relative length of a Haskell string and its corresponding C string, and therefore, all routines provided by CString combine memory allocation and marshalling. The translation between Unicode and the encoding of the current locale may be lossy. The function charIsRepresentable identifies the characters that can be accurately translated; unrepresentable characters are converted to ‘?’.

type CString = Ptr CChar
A C string is a reference to an array of C characters terminated by NUL.
type CStringLen = (Ptr CChar, Int)
In addition to NUL-terminated strings, the module CString also supports strings with explicit length information in bytes.
peekCString    :: CString    -> IO String
peekCStringLen :: CStringLen -> IO String
Marshal a C string to Haskell. There are two variants of the routine, one for each supportedstring representation.
newCString    :: String -> IO CString
newCStringLen :: String -> IO CStringLen
Allocate a memory area for a Haskell string and marshal the string into its C representation.There are two variants of the routine, one for each supported string representation. The memory area allocated by these routines may be deallocated using MarshalAlloc.free.
withCString    :: String -> (CString    -> IO a) -> IO a
withCStringLen :: String -> (CStringLen -> IO a) -> IO a
These two routines operate as newCString and newCStringLen, respectively, but handlememory allocation and deallocation like MarshalAlloc.alloca (Section 5.8).
charIsRepresentable :: Char -> IO Bool
Determine whether the argument can be represented in the current locale.

Some C libraries require to ignore the Unicode capabilities of Haskell and treat values of type Char as single byte characters. Hence, the module CString provides a variant of the above marshalling routines that truncates character sets correspondingly. These functions should be used with care, as a loss of information can occur.

castCharToCChar :: Char -> CChar
castCCharToChar :: CChar -> Char
These two functions cast Haskell characters to C characters and vice versa while ignoringthe Unicode encoding of the Haskell character. More precisely, only the first 256 character points are preserved.
peekCAString    :: CString    -> IO String
peekCAStringLen :: CStringLen -> IO String
newCAString     :: String -> IO CString
newCAStringLen  :: String -> IO CStringLen
withCAString    :: String -> (CString    -> IO a) -> IO a
withCAStringLen :: String -> (CStringLen -> IO a) -> IO a
These functions for whole-string marshalling cast Haskell characters to C characters andvice versa while ignoring the Unicode encoding of Haskell characters.

To simplify bindings to C libraries that use wchar_t for character sets that cannot be encoded in byte strings, the module CString also exports a variant of the above string marshalling routines for wide characters--i.e., for the C wchar_t type.2

type CWString    = Ptr CWchar
type CWStringLen = (Ptr CWchar, Int)
Wide character strings in a NUL-terminated version and a variant with explicit lengthinformation in number of wide characters.
peekCWString    :: CWString    -> IO String
peekCWStringLen :: CWStringLen -> IO String
newCWString     :: String -> IO CWString
newCWStringLen  :: String -> IO CWStringLen
withCWString    :: String -> (CWString    -> IO a) -> IO a
withCWStringLen :: String -> (CWStringLen -> IO a) -> IO a
String marshalling for wide character strings. The interface is the same as for byte strings.

6.4 CError

The module CError facilitates C-specific error handling of errno. In Haskell, we represent values of errno by

newtype Errno = Errno CInt

which has an instance for the type class Eq. The implementation of Errno is disclosed on purpose. Different operating systems and/or C libraries often support different values of errno. This module defines the common values, but due to the open definition of Errno users may add definitions which are not predefined. The predefined values are the following:

eOK, e2BIG, eACCES, eADDRINUSE, eADDRNOTAVAIL, eADV, eAFNOSUPPORT, eAGAIN,  
  eALREADY, eBADF, eBADMSG, eBADRPC, eBUSY, eCHILD, eCOMM, eCONNABORTED,  
  eCONNREFUSED, eCONNRESET, eDEADLK, eDESTADDRREQ, eDIRTY, eDOM, eDQUOT,  
  eEXIST, eFAULT, eFBIG, eFTYPE, eHOSTDOWN, eHOSTUNREACH, eIDRM, eILSEQ,  
  eINPROGRESS, eINTR, eINVAL, eIO, eISCONN, eISDIR, eLOOP, eMFILE, eMLINK,  
  eMSGSIZE, eMULTIHOP, eNAMETOOLONG, eNETDOWN, eNETRESET, eNETUNREACH,  
  eNFILE, eNOBUFS, eNODATA, eNODEV, eNOENT, eNOEXEC, eNOLCK, eNOLINK,  
  eNOMEM, eNOMSG, eNONET, eNOPROTOOPT, eNOSPC, eNOSR, eNOSTR, eNOSYS,  
  eNOTBLK, eNOTCONN, eNOTDIR, eNOTEMPTY, eNOTSOCK, eNOTTY, eNXIO,  
  eOPNOTSUPP, ePERM, ePFNOSUPPORT, ePIPE, ePROCLIM, ePROCUNAVAIL,  
  ePROGMISMATCH, ePROGUNAVAIL, ePROTO, ePROTONOSUPPORT, ePROTOTYPE,  
  eRANGE, eREMCHG, eREMOTE, eROFS, eRPCMISMATCH, eRREMOTE, eSHUTDOWN,  
  eSOCKTNOSUPPORT, eSPIPE, eSRCH, eSRMNT, eSTALE, eTIME, eTIMEDOUT,  
  eTOOMANYREFS, eTXTBSY, eUSERS, eWOULDBLOCK, eXDEV  
  :: Errno

The meaning of these values corresponds to that of the C constants of the same name with the leading ”e” converted to upper-case.

The module CError provides the following functions:

isValidErrno :: Errno -> Bool
Yield True if the given Errno value is valid on the system. This implies that the Eq instance of Errno is also system dependent as it is only defined for valid values of Errno.
getErrno :: IO Errno
Get the current value of errno.
resetErrno :: IO ()
Reset errno to eOK.
errnoToIOError :: String -> Errno -> Maybe Handle -> Maybe String -> IOError
Compute a Haskell 98 I/O error based on the given Errno value. The first argument to the function should specify the location where the error occurred and the third and fourth can be used to specify a file handle and filename in the course of whose manipulation the error occurred. This is optional information, which can be used to improve the accuracy of error messages.
throwErrno :: String -> IO a
Apply errnoToIOError to the value currently returned by getErrno. Its first argument specifies the location--no extra information about a file handle or filename can be provided in this case.
throwErrnoIf  :: (a -> Bool) -> String -> IO a -> IO a
throwErrnoIf_ :: (a -> Bool) -> String -> IO a -> IO ()
Behave like throwErrno in case that the result of the IO action fulfils the predicate passedas a first argument. The second variant discards the result after error handling.
throwErrnoIfRetry  :: (a -> Bool) -> String -> IO a -> IO a
throwErrnoIfRetry_ :: (a -> Bool) -> String -> IO a -> IO ()
Like throwErrnoIf and throwErrnoIf_, but retry the IO action when it yields the errorcode eINTR--this amounts to the standard retry loop for interrupted POSIX system calls.
throwErrnoIfMinus1  :: Num a => String -> IO a -> IO a
throwErrnoIfMinus1_ :: Num a => String -> IO a -> IO ()
Instantiate throwErrnoIf and throwErrnoIf_ with the predicate (== -1).
throwErrnoIfMinus1Retry  :: Num a => String -> IO a -> IO a
throwErrnoIfMinus1Retry_ :: Num a => String -> IO a -> IO ()
Instantiate throwErrnoIfRetry and throwErrnoIfRetry_ with the predicate (== -1).
throwErrnoIfNull      :: String -> IO (Ptr a) -> IO (Ptr a)
throwErrnoIfNullRetry :: String -> IO (Ptr a) -> IO (Ptr a)
Instantiate throwErrnoIf and throwErrnoIfRetry with the predicate (== Ptr.nullPtr).