X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=docs%2Fffi.sgml;h=bb5d78b9a257574a30b6eba9d976181bba7840bf;hp=e59ff9e42e7c42eb6908c1f3ff3395156edb64b3;hb=cab3c5cb1a0038412472172cb0b25bc81dfdde8f;hpb=14f3d572dc00dada527b0cb55de03b05a115064a diff --git a/docs/ffi.sgml b/docs/ffi.sgml index e59ff9e..bb5d78b 100644 --- a/docs/ffi.sgml +++ b/docs/ffi.sgml @@ -1,35 +1,32 @@ - + 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 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. However, 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 GreenCard, both +of which are capable of generating Haskell code that uses this FFI. -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 +In the following, we will discuss the language extensions of the FFI. +The extensions 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 @@ -63,12 +60,12 @@ 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 +type of the external function. + specifies the mapping from Haskell types to external types. - + Giving the external function a Haskell name @@ -96,103 +93,46 @@ 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: +The name of the external function is a string: - - -ext_fun : ext_loc ext_name - | ext_name - -ext_name : string -ext_loc : string - - - +ext_fun : string For example, - - -foreign import stdcall "Advapi32" "RegCloseKey" regCloseKey :: Addr -> IO () +foreign import stdcall "RegCloseKey" regCloseKey :: Ptr a -> 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. - +states that the external function named RegCloseKey should be bound to the Haskell name 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. - +The details of where exactly the external name can be found, such as +whether or not it is dynamically linked, and which library it might +come from, are implementation dependent. This information is expected +to be provided using a compiler-specific method (eg. GHC uses either +packages or command-line options to specify libraries and extra +include files). -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., +If the Haskell name of the imported function is identical to the +external name, the ext_fun can be +omitted. e.g.: -foreign import sin :: Double -> IO Double +foreign import sin :: Double -> IO Double @@ -204,14 +144,14 @@ is identical to -foreign import "sin" sin :: Double -> IO Double +foreign import "sin" sin :: Double -> IO Double - + Calling conventions @@ -254,7 +194,7 @@ that the callee cleans up the C stack before returning. -The stdcall is a Microsoft Win32 specific wrinkle; it used +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. @@ -312,7 +252,7 @@ to leave out the specification of the calling convention, if possible. - + External function types @@ -326,7 +266,7 @@ function is restricted (as are the range of results coming back): prim_type : IO prim_result | prim_result - | prim_arg '->' prim_type + | prim_arg '->' prim_type @@ -348,40 +288,18 @@ have the same 'proof obligations' as when you make use of 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_result; defines prim_arg. - + Argument types @@ -393,12 +311,12 @@ argument types is restricted to the following set: -prim_arg : ext_ty | new_ty | ForeignObj +prim_arg : ext_ty | new_ty | ForeignPtr a new_ty : a Haskell newtype of a prim_arg. ext_ty : int_ty | word_ty | float_ty - | Addr | Char | StablePtr a + | Ptr a | Char | StablePtr a | Bool int_ty : Int | Int8 | Int16 | Int32 | Int64 @@ -419,7 +337,7 @@ 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 +C mapping, see for details. @@ -427,23 +345,27 @@ for details. -prim_arg represent the set of permissible argument types. In -addition to ext_ty, ForeignObj is also included. +prim_arg represent the set of permissible +argument types. In addition to ext_ty, +ForeignPtr 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. +The ForeignPtr type represent values that are +pointers to some external entity/object. It differs from the +Ptr type in that ForeignPtrs are +finalized, i.e., once the garbage collector +determines that a ForeignPtr is unreachable, it +will invoke a finalising procedure attached to the +ForeignPtr 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 newtypes that wrap up a +prim_arg type can also be passed to external +functions. @@ -463,46 +385,10 @@ constants/variables. A foreign import declaration that takes 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: +A GHC extension is the support for unboxed types: @@ -527,15 +413,10 @@ be withdrawn sometime in the future.) - - - - - - + Result type @@ -572,8 +453,9 @@ 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. +Only external types (ext_ty) can be passed +back, i.e., returning ForeignPtrs is not +supported/allowed. @@ -591,7 +473,7 @@ Haskell newtypes that wrap up ext_ty are also permitte - + Type mapping @@ -601,18 +483,16 @@ 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 - - - + @@ -729,29 +609,25 @@ defines the mapping between Haskell and C types. -Addr - HsAddr +Ptr a + HsPtr void* (6) -ForeignObj - HsForeignObj +ForeignPtr a + HsForeignPtr void* (7) -StablePtr +StablePtr a HsStablePtr void* (8) - - - - @@ -816,8 +692,8 @@ 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 +Foreign objects are handled like Ptr by the FFI, so there +is again the guarantee that HsForeignPtr is the same as void*. The separate name is meant as a reminder that there is a finalizer attached to the object pointed to. @@ -889,7 +765,7 @@ macros starting with HS_ are reserved for the FFI. - + Some <Literal>foreign import</Literal> wrinkles @@ -904,12 +780,12 @@ 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 + 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 +'unsafe' (see for details of how to do this.) Unsafe calls are cheaper than safe ones, so distinguishing the two @@ -928,25 +804,27 @@ equal that of a normal C call. For instance, for the following decl, -foreign import "mumble" mumble :: ForeignObj -> IO () +foreign import "mumble" mumble :: ForeignPtr a -> IO () -f :: Addr -> IO () +f :: Ptr a -> IO () f ptr = do - fo <- makeForeignObj ptr myFinalizer + fo <- newForeignObj 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. +The ForeignPtr 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 +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. @@ -961,7 +839,7 @@ valid) is avoided. - + Invoking external functions via a pointer @@ -986,7 +864,7 @@ topdecl : ... .. | 'foreign' 'import' [callconv] 'dynamic' ['unsafe'] - varid :: Addr -> (prim_args -> IO prim_result) + varid :: Addr -> (prim_args -> IO prim_result) @@ -1014,7 +892,7 @@ and execute code. - + Exposing Haskell functions @@ -1048,7 +926,7 @@ convention to use. For instance, the following export declaration: -foreign export ccall "foo" bar :: Int -> Addr -> IO Double +foreign export ccall "foo" bar :: Int -> Addr -> IO Double @@ -1098,9 +976,9 @@ this is legal: - f :: Num a => a -> a - foreign export ccall "fInt" f :: Int -> Int - foreign export ccall "fFloat" f :: Float -> Float + f :: Num a => a -> a + foreign export ccall "fInt" f :: Int -> Int + foreign export ccall "fFloat" f :: Float -> Float @@ -1123,7 +1001,7 @@ outside world. - + Exposing Haskell function values @@ -1141,7 +1019,7 @@ function pointers though. To permit this, the FFI supports topdecl : ... .. - | 'foreign' 'export' [callconv] 'dynamic' varid :: prim_type -> IO Addr + | 'foreign' 'export' [callconv] 'dynamic' varid :: prim_type -> IO Addr @@ -1176,7 +1054,7 @@ typedef cType[[Res]] (*Varid_FunPtr) where cType[[]] is the Haskell to C type mapping presented -in Section . +in . @@ -1186,11 +1064,11 @@ To make it all a bit more concrete, here's an example: -foreign export dynamic mkCallback :: (Int -> IO Int) -> IO Addr +foreign export dynamic mkCallback :: (Int -> IO Int) -> IO Addr -foreign import registerCallback :: Addr -> IO () +foreign import registerCallback :: Addr -> IO () -exportCallback :: (Int -> IO Int) -> IO () +exportCallback :: (Int -> IO Int) -> IO () exportCallback f = do fx <- mkCallback f registerCallback fx @@ -1248,14 +1126,14 @@ point is also provided, -Foreign.freeHaskellFunctionPtr :: Addr -> IO () +Foreign.freeHaskellFunctionPtr :: Addr -> IO () - + Code addresses @@ -1286,7 +1164,7 @@ contain the address of the label freeAtLast.