From: rrt Date: Wed, 7 Jun 2000 16:15:22 +0000 (+0000) Subject: [project @ 2000-06-07 16:15:22 by rrt] X-Git-Tag: Approximately_9120_patches~4314 X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=8e5eb3dfef0debc9bf9f914b1a5f5fe3d2717f89 [project @ 2000-06-07 16:15:22 by rrt] DocBooked and moved here from hdirect/doc. --- diff --git a/docs/ffi.sgml b/docs/ffi.sgml new file mode 100644 index 0000000..85f8bcf --- /dev/null +++ b/docs/ffi.sgml @@ -0,0 +1,1501 @@ + + +
+ + + +A Haskell foreign function interface +The GHC Team +
glasgow-haskell-{users,bugs}@dcs.gla.ac.uk +
+version 0.99 +May 2000 + +
+ + +Introduction + + + +The motivation behind this foreign function interface(FFI) +specification is to make it possible to describe in Haskell source +code the interface to foreign functionality in a Haskell system +independent manner. It builds on experiences made with the previous +foreign function interfaces provided by GHC and Hugs. + + + +The FFI specified in this document is not in the market of trying to +completely bridge the gap between the actual type of an external +function, and what is a convenient type for that function to the +Haskell programmer. That is the domain of tools like HaskellDirect or +Green Card, both of which are capable of generating Haskell code that +uses this FFI. + + + +The FFI can be split up into two complementary halves; one half that +provides Haskell constructs for importing foreign functionality into +Haskell, the other which lets you expose Haskell functions to the +outside world. We start with the former, how to import external +functionality into Haskell. + + + + + +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: + + + + + +topdecl + : ... + .. + | '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 + specifies the mapping from +Haskell types to external types. + + + +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 '. + + + +Notice that with Haskell 98, underscore ('_') is included in +the character class small. + + + + + + + +varid : small ( small | large | udigit | ' )* + + + + + + +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 + + + + + + + +Calling conventions + + + +The number of calling conventions supported is fixed: + + + + + +callconv : ccall | stdcall + + + + + + + + +ccall + + +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. + + + + +stdcall + + +A Win32 specific calling convention. The same as ccall, except +that the callee cleans up the C stack before returning. + + + +The stdcall is a Microsoft Win32 specific wrinkle; it used +throughout the Win32 API, for instance. On platforms where +stdcall isn't meaningful, it should be treated as being equal +to ccall. + + + + + + + + + + +Some remarks: + + + + + +Interoperating well with external code is the name of the game here, +so the guiding principle when deciding on what calling conventions +to include in callconv is that there's a demonstrated need for +a particular calling convention. Should it emerge that the inclusion +of other calling conventions will generally improve the quality of +this Haskell FFI, they will be considered for future inclusion in +callconv. + + + + + +Supporting stdcall (and perhaps other platform-specific calling +conventions) raises the issue of whether a Haskell FFI should allow +the user to write platform-specific Haskell code. The calling +convention is clearly an integral part of an external function's +interface, so if the one used differs from the standard one specified +by the platform's ABI and that convention is used by a +non-trivial amount of external functions, the view of the FFI authors +is that a Haskell FFI should support it. + + + + + +For foreign import (and other foreign declarations), +supplying the calling convention is optional. If it isn't supplied, +it is treated as if ccall was specified. Users are encouraged +to leave out the specification of the calling convention, if possible. + + + + + + + + + + +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 + + + + + + + + + + +If you associate a non-IO type with an external function, you +have the same 'proof obligations' as when you make use of +IOExts.unsafePerformIO in your Haskell programs. + + + + + +The external function is strict in all its arguments. + + + + + +GHC only: The GHC FFI implementation provides one extension +to prim_type: + + + +prim_type : ... + | unsafe_arr_ty '->' prim_type + +unsafe_arr_ty : ByteArray a + | MutableByteArray i s a + + + +GHC permits the passing of its byte array primitive types +to external functions. There's some restrictions on when +they can be used; see Section +for more details. + + + + + + + + +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 +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. + + + + + + + + + + + + +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 + +defines the mapping between Haskell and C types. + + + + + +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: + + + + + +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. + + + + + +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. + + + + + +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. + + + + + +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. + + + + + +It is guaranteed that Hs{Float,Double} are one of C's +floating-point types float/double/long double. + + + + + +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). + + + + + +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. + + + + + +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. + + + + + +The bounds are preprocessor macros, so they can be used in +#if and for array bounds. + + + + + +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 + + + + + + + +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. + + + + + +To avoid name clashes, identifiers starting with Hs and +macros starting with HS_ are reserved for the FFI. + + + + + +GHC only: The GHC specific types ByteArray and +MutableByteArray both map to char*. + + + + + + + +
+ + +Some <Literal>foreign import</Literal> wrinkles + + + + + + + + +By default, a foreign import function is safe. A safe +external function may cause a Haskell garbage collection as a result +of being called. This will typically happen when the imported +function end up calling Haskell functions that reside in the same +'Haskell world' (i.e., shares the same storage manager heap) -- see +Section for +details of how the FFI let's you call Haskell functions from the outside. + +If the programmer can guarantee that the imported function won't +call back into Haskell, the foreign import can be marked as +'unsafe' (see Section for details of +how to do this.) + +Unsafe calls are cheaper than safe ones, so distinguishing the two +classes of external calls may be worth your while if you're extra +conscious about performance. + + + + + + +A foreign imported function should clearly not need to know that +it is being called from Haskell. One consequence of this is that the +lifetimes of the arguments that are passed from Haskell must +equal that of a normal C call. For instance, for the following decl, + + + +foreign import "mumble" mumble :: ForeignObj -> IO () + +f :: Addr -> IO () +f ptr = do + fo <- makeForeignObj ptr myFinalizer + mumble fo + + + +The ForeignObj must live across the call to mumble even if +it is not subsequently used/reachable. Why the insistence on this? +Consider what happens if mumble calls a function which calls back +into the Haskell world to execute a function, behind our back as it +were. This evaluation may possibly cause a garbage collection, with +the result that fo may end up being finalised. + +By guaranteeing that fo will be considered live across the call +to mumble, the unfortunate situation where fo is finalised +(and hence the reference passed to mumble is suddenly no longer +valid) is avoided. + + + + + + + + + + + +
+ + +Invoking external functions via a pointer + + + +A foreign import declaration imports an external +function into Haskell. (The name of the external function +is statically known, but the loading/linking of it may very well +be delayed until run-time.) A foreign import declaration is then +(approximately) just a type cast of an external function with a +statically known name. + + + +An extension of foreign import is the support for dynamic type +casts of external names/addresses: + + + + + +topdecl + : ... + .. + | 'foreign' 'import' [callconv] 'dynamic' ['unsafe'] + varid :: Addr -> (prim_args -> IO prim_result) + + + + + +i.e., identical to a foreign import declaration, but for the +specification of dynamic instead of the name of an external +function. The presence of dynamic indicates that when an +application of varid is evaluated, the function pointed to by its +first argument will be invoked, passing it the rest of varid's +arguments. + + + +What are the uses of this? Native invocation of COM methods, + + +Or the interfacing to any other software component technologies. + + +Haskell libraries that want to be dressed up as C libs (and hence may have +to support C callbacks), Haskell code that need to dynamically load +and execute code. + + + + + +Exposing Haskell functions + + + +So far we've provided the Haskell programmer with ways of importing +external functions into the Haskell world. The other half of the FFI +coin is how to expose Haskell functionality to the outside world. So, +dual to the foreign import declaration is foreign export: + + + + + +topdecl + : ... + .. + | 'foreign' 'export' callconv [ext_name] varid :: prim_type + + + + + +A foreign export declaration tells the compiler to expose a +locally defined Haskell function to the outside world, i.e., wrap +it up behind a calling interface that's useable from C. It is only +permitted at the toplevel, where you have to specify the type at +which you want to export the function, along with the calling +convention to use. For instance, the following export declaration: + + + + + +foreign export ccall "foo" bar :: Int -> Addr -> IO Double + + + + + +will cause a Haskell system to generate the following C callable +function: + + + + + +HsDouble foo(HsInt arg1, HsAddr arg2); + + + + + +When invoked, it will call the Haskell function bar, passing +it the two arguments that was passed to foo(). + + + + + + + + +The range of types that can be passed as arguments and results +is restricted, since varid has got a prim_type. + + + + + +It is not possible to directly export operator symbols. + + + + + +The type checker will verify that the type given for the +foreign export declaration is compatible with the type given to +function definition itself. The type in the foreign export may +be less general than that of the function itself. For example, +this is legal: + + + + f :: Num a => a -> a + foreign export ccall "fInt" f :: Int -> Int + foreign export ccall "fFloat" f :: Float -> Float + + + +These declarations export two C-callable procedures fInt and +fFloat, both of which are implemented by the (overloaded) +Haskell function f. + + + + + + +The foreign exported IO action must catch all exceptions, as +the FFI does not address how to signal Haskell exceptions to the +outside world. + + + + + + + + +Exposing Haskell function values + + + +The foreign export declaration gives the C programmer access to +statically defined Haskell functions. It does not allow you to +conveniently expose dynamically-created Haskell function values as C +function pointers though. To permit this, the FFI supports +dynamic foreign exports: + + + + + +topdecl + : ... + .. + | 'foreign' 'export' [callconv] 'dynamic' varid :: prim_type -> IO Addr + + + + + +A foreign export dynamic declaration declares a C function +pointer generator. Given a Haskell function value of some restricted +type, the generator wraps it up behind an externally callable interface, +returning an Addr to an externally callable (C) function pointer. + + + +When that function pointer is eventually called, the corresponding +Haskell function value is applied to the function pointer's arguments +and evaluated, returning the result (if any) back to the caller. + + + +The mapping between the argument to a foreign export dynamic +declaration and its corresponding C function pointer type, is as +follows: + + + + + +typedef cType[[Res]] (*Varid_FunPtr) + (cType[[Ty_1]] ,.., cType[[Ty_n]]); + + + + + +where cType[[]] is the Haskell to C type mapping presented +in Section . + + + +To make it all a bit more concrete, here's an example: + + + + + +foreign export dynamic mkCallback :: (Int -> IO Int) -> IO Addr + +foreign import registerCallback :: Addr -> IO () + +exportCallback :: (Int -> IO Int) -> IO () +exportCallback f = do + fx <- mkCallback f + registerCallback fx + + + + + +The exportCallback lets you register a Haskell function value as +a callback function to some external library. The C type of the +callback that the external library expects in registerCallback(), +is: + + +An FFI implementation is encouraged to generate the C typedef corresponding +to a foreign export dynamic declaration, but isn't required +to do so. + + + + + + + + +typedef HsInt (*mkCallback_FunPtr) (HsInt arg1); + + + + + +Creating the view of a Haskell closure as a C function pointer entails +registering the Haskell closure as a 'root' with the underlying +Haskell storage system, so that it won't be garbage collected. The FFI +implementation takes care of this, but when the outside world is +through with using a C function pointer generated by a foreign +export dynamic declaration, it needs to be explicitly freed. This is +done by calling: + + + + + +void freeHaskellFunctionPtr(void *ptr); + + + + + +In the event you need to free these function pointers from within +Haskell, a standard 'foreign import'ed binding of the above C entry +point is also provided, + + + + + +Foreign.freeHaskellFunctionPtr :: Addr -> IO () + + + + + + + +Code addresses + + + +The foreign import declaration allows us to invoke an external +function by name from within the comforts of the Haskell world, while +foreign import dynamic lets us invoke an external function by +address. However, there's no way of getting at the code address of +some particular external label though, which is at times useful, +e.g. for the construction of method tables for, say, Haskell COM +components. To support this, the FFI has got foreign labels: + + + + + +foreign label "freeAtLast" addrOf_freeAtLast :: Addr + + + + + +The meaning of this declaration is that addrOf_freeAtLast will now +contain the address of the label freeAtLast. + + + + + + + +Change history + + + + + + + + +0.95 --> 0.96: + + + + + +changed the C representation of Haskell_ForeignObj from +(long*) to (void*) -- ANSI C guarantees that (void*) +is the widest possible data pointer. + + + + + +Updated defnition of varid in Section + to reflect Haskell98's. + + + + + +Replaced confusing uses of stdcall with ccall. + + + + + + + + + + +0.96 --> 0.97: + + + + + +Simplified the calling convention section, support for Pascal (and +fastcall) calling conventions dropped. + + + + + +Clarified that the arguments to a safe foreign import must have +lifetimes that equal that of a C function application. + + + + + +Outlawed the use of the (GHC specific) types ByteArray +and MutableByteArray in safe foreign imports. + + + + + +Added a note that support for the use of unboxed types in +foreign import may be withdrawn/deprecated sometime in the future. + + + + + +Simplified section which sketches a possible implementation. + + + + + +Use Hs as prefix for the typedefs for the primitive Haskell +FFI types rather than the longer Haskell_. + + + + + + + + + + +0.97 --> 0.98: + + + + + +Leave out implementation section; of limited interest. + + + + + +Outlined the criteria used to decide on what calling +conventions to support. + + + + + +Include newtypes that wrap primitive types in the list +of types that can be both passed to and returned from external +functions. + + + + + + + + + + +0.98 --> 0.99: + + + + + +Updated the section on type mapping to integrate some comments +from people on <ffi@haskell.org> (a fair chunk of the text +in that section was contributed by Sven Panne.) + + + + + +freeHaskellFunctionPtr should belong to module Foreign, not IOExts. + + + + + + + + + + + +0.99 --> 0.99.1: + + + + + +Bool is now an FFI-supported type (i.e., added it to +ext_ty.) + + + + + + + + + + + + + + + +