The module CForeign combines the interfaces of all modules providing C-specific marshalling support. The modules are CTypes, CString, and CError.
|
|
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.
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 type | Represented 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 type | Represented 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 type | Represented C type | |
CPtrdiff | ptrdiff_t | |
CSize | size_t | |
CWchar | wchar_t | |
CSigAtomic | sig_atomic_t | |
Moreover, it provides the following numeric types, including instances for Eq, Ord, Num, Read, Show, Enum, and Storable:
Haskell type | Represented C type | |
CClock | clock_t | |
CTime | time_t | |
And finally, the following types, including instances for Eq and Storable, are provided:
Haskell type | Represented C type | |
CFile | FILE | |
CFpos | fpos_t | |
CJmpBuf | jmp_buf | |
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 ‘?’.
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.
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
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: