From: simonmar Date: Mon, 17 Sep 2001 09:51:23 +0000 (+0000) Subject: [project @ 2001-09-17 09:51:23 by simonmar] X-Git-Tag: Approximately_9120_patches~971 X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=488d5cc391d0bec3575528a9cb88ae0b12ee0fb9 [project @ 2001-09-17 09:51:23 by simonmar] Knock the FFI documentation into some sort of shape for the release: - The blurb about "the FFI is in two/three parts..." was repeated in three places. We also at some point seem to have lost the property that the FFI spec is a self-contained document; I don't try to fix that here, since we're going to replace it with the new spec at some point. - Replace references to Addr and ForeignObj with Ptr and ForeignPtr. - Remove mentions of GHC's ByteArray and MutableByteArray types, as these are deprecated and will be removed in a couple of versions. (mostly subsumed by allocaBytes and friends). - Catch up with GHC's removal of the library specification from foreign import. Mention that libraries are specified in a compiler-dependent way now, and that GHC uses either packages or command-line opts for this. - Fix up some markup. --- diff --git a/docs/ffi.sgml b/docs/ffi.sgml index 0cc2aca..067f790 100644 --- a/docs/ffi.sgml +++ b/docs/ffi.sgml @@ -16,63 +16,12 @@ of which are capable of generating Haskell code that uses this FFI. -Generally, the FFI consists of three parts: - - - - -extensions to the base language Haskell 98 (most notably foreign -import and foreign export declarations), which -are specified in the present document, - - - - - -a low-level marshalling library, which is part of the -Language part of the Haskell Extension -Library (see ), and a - - - - - -a high-level marshalling library, which is still under development. - - - - -Before diving into the details of the language extension coming with the FFI, -let us briefly outline the two other components of the interface. - - - -The low-level marshalling library consists of a portion that is independent of -the targeted foreign language and dedicated support for Haskell bindings to C -libraries (special support for other languages may be added in the future). -The language independent part is given by the module -Foreign module (see ). It -provides support for handling references to foreign structures, for passing -references to Haskell structures out to foreign routines, and for storing -primitive data types in raw memory blocks in a portable manner. The support -for C libraries essentially provides Haskell representations for all basic -types of C (see and ). - - - -The high-level library, of which the interface definition is not yet -finalised, provides routines for marshalling complex Haskell structures as -well as handling out and in-out parameters in a convenient, yet protable way. - - - -In the following, we will discuss the language extensions of the FFI (i.e. the -first point above). They 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. +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. @@ -149,98 +98,41 @@ varid : small ( small | large | udigit | ' )* -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 +If the Haskell name of the imported function is identical to the +external name, the ext_fun can be +omitted. e.g.: -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 +foreign import sin :: Double -> IO Double @@ -252,7 +144,7 @@ is identical to -foreign import "sin" sin :: Double -> IO Double +foreign import "sin" sin :: Double -> IO Double @@ -374,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 @@ -396,28 +288,6 @@ 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 -for more details. - - @@ -441,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 @@ -475,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. @@ -511,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: @@ -575,11 +413,6 @@ be withdrawn sometime in the future.) - - - - - @@ -620,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. @@ -775,21 +609,21 @@ 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) @@ -858,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. @@ -970,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 <- 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. @@ -1028,7 +864,7 @@ topdecl : ... .. | 'foreign' 'import' [callconv] 'dynamic' ['unsafe'] - varid :: Addr -> (prim_args -> IO prim_result) + varid :: Addr -> (prim_args -> IO prim_result) @@ -1090,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 @@ -1140,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 @@ -1183,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 @@ -1228,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 @@ -1290,7 +1126,7 @@ point is also provided, -Foreign.freeHaskellFunctionPtr :: Addr -> IO () +Foreign.freeHaskellFunctionPtr :: Addr -> IO () @@ -1344,9 +1180,11 @@ contain the address of the label freeAtLast. -changed the C representation of Haskell_ForeignObj from -(long*) to (void*) ANSI C guarantees that (void*) -is the widest possible data pointer. +changed the C representation of +Haskell_ForeignPtr from +(long*) to (void*) ANSI C +guarantees that (void*) is the widest possible data +pointer. diff --git a/ghc/docs/users_guide/ffi-chap.sgml b/ghc/docs/users_guide/ffi-chap.sgml index d0f6878..c2d7b83 100644 --- a/ghc/docs/users_guide/ffi-chap.sgml +++ b/ghc/docs/users_guide/ffi-chap.sgml @@ -3,7 +3,8 @@ Foreign function interface - The foreign interface consists of the following components: + The foreign function interface consists of the following + components: @@ -16,44 +17,11 @@ - The Foreign module (see ) collects together several interfaces - which are useful in specifying foreign language interfaces, - including the following: - - - - The ForeignObj module (see ), for managing pointers from - Haskell into the outside world. - - - - The StablePtr module (see ), for managing pointers into - Haskell from the outside world. - - - - The CTypes module (see ) gives Haskell equivalents for the - standard C datatypes, for use in making Haskell bindings to - existing C libraries. - - - - The CTypesISO module (see ) gives Haskell equivalents for C - types defined by the ISO C standard. - - - - The Storable library, for primitive - marshalling of data types between Haskell and the foreign - language. - - - + Several library modules which provide access to types used + by foreign languages and utilties for marshalling values to and + from foreign functions, and for converting errors in the foreign + language into Haskell IO errors. See for + more details.