X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fffi-chap.xml;h=97a237876ff69a4d0f865f7faea4b0dedfccc4ff;hb=6cec61d14a324285dbb8ce73d4c7215f1f8d6766;hp=e1374c461054f54a2d2b9f085d8ae92cda03101c;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml index e1374c4..97a2378 100644 --- a/docs/users_guide/ffi-chap.xml +++ b/docs/users_guide/ffi-chap.xml @@ -6,41 +6,26 @@ Foreign function interface (FFI) - GHC (mostly) conforms to the Haskell 98 Foreign Function Interface - Addendum 1.0, whose definition is available from http://haskell.org/. - - To enable FFI support in GHC, give the - flag, or -the - flag which implies -. - - The FFI support in GHC diverges from the Addendum in the following ways: - - - - Syntactic forms and library functions proposed in earlier versions - of the FFI are still supported for backwards compatibility. - - - - GHC implements a number of GHC-specific extensions to the FFI - Addendum. These extensions are described in , but please note that programs using - these features are not portable. Hence, these features should be - avoided where possible. - - + GHC (mostly) conforms to the Haskell Foreign Function Interface, + whose definition is part of the Haskell Report on http://www.haskell.org/. + + FFI support is enabled by default, but can be enabled or disabled explicitly with the + flag. + + GHC implements a number of GHC-specific extensions to the FFI + Addendum. These extensions are described in , but please note that programs using + these features are not portable. Hence, these features should be + avoided where possible. The FFI libraries are documented in the accompanying library - documentation; see for example the Foreign - module. + documentation; see for example the + Foreign module. - + GHC extensions to the FFI Addendum The FFI features that are described in this section are specific to - GHC. Avoid them where possible to not compromise the portability of the - resulting code. + GHC. Your code will not be portable to other compilers if you use them. Unboxed types @@ -54,9 +39,128 @@ the + + Newtype wrapping of the IO monad + The FFI spec requires the IO monad to appear in various places, + but it can sometimes be convenient to wrap the IO monad in a + newtype, thus: + + newtype MyIO a = MIO (IO a) + + (A reason for doing so might be to prevent the programmer from + calling arbitrary IO procedures in some part of the program.) + +The Haskell FFI already specifies that arguments and results of +foreign imports and exports will be automatically unwrapped if they are +newtypes (Section 3.2 of the FFI addendum). GHC extends the FFI by automatically unwrapping any newtypes that +wrap the IO monad itself. +More precisely, wherever the FFI specification requires an IO type, GHC will +accept any newtype-wrapping of an IO type. For example, these declarations are +OK: + + foreign import foo :: Int -> MyIO Int + foreign import "dynamic" baz :: (Int -> MyIO Int) -> CInt -> MyIO Int + + + + + + Primitive imports + + GHC extends the FFI with an additional calling convention + prim, e.g.: + + foreign import prim "foo" foo :: ByteArray# -> (# Int#, Int# #) + + This is used to import functions written in Cmm code that follow an + internal GHC calling convention. This feature is not intended for + use outside of the core libraries that come with GHC. For more + details see the GHC developer wiki. + + + + + Interruptible foreign calls + + This concerns the interaction of foreign calls + with Control.Concurrent.throwTo. + Normally when the target of a throwTo is + involved in a foreign call, the exception is not raised + until the call returns, and in the meantime the caller is + blocked. This can result in unresponsiveness, which is + particularly undesirable in the case of user interrupt + (e.g. Control-C). The default behaviour when a Control-C + signal is received (SIGINT on Unix) is to raise + the UserInterrupt exception in the main + thread; if the main thread is blocked in a foreign call at + the time, then the program will not respond to the user + interrupt. + + + + The problem is that it is not possible in general to + interrupt a foreign call safely. However, GHC does provide + a way to interrupt blocking system calls which works for + most system calls on both Unix and Windows. A foreign call + can be annotated with interruptible instead + of safe or unsafe: + + +foreign import ccall interruptible + "sleep" :: CUint -> IO CUint + + + interruptble behaves exactly as + safe, except that when + a throwTo is directed at a thread in an + interruptible foreign call, an OS-specific mechanism will be + used to attempt to cause the foreign call to return: + + + + Unix systems + + + The thread making the foreign call is sent + a SIGPIPE signal + using pthread_kill(). This is + usually enough to cause a blocking system call to + return with EINTR (GHC by default + installs an empty signal handler + for SIGPIPE, to override the + default behaviour which is to terminate the process + immediately). + + + + + Windows systems + + + [Vista and later only] The RTS calls the Win32 + function CancelSynchronousIO, + which will cause a blocking I/O operation to return + with the + error ERROR_OPERATION_ABORTED. + + + + + + If the system call is successfully interrupted, it will + return to Haskell whereupon the exception can be raised. Be + especially careful when + using interruptible that the caller of + the foreign function is prepared to deal with the + consequences of the call being interrupted; on Unix it is + good practice to check for EINTR always, + but on Windows it is not typically necessary to + handle ERROR_OPERATION_ABORTED. + + - + Using the FFI with GHC The following sections also give some hints and tips on the @@ -112,6 +216,13 @@ extern HsInt foo(HsInt a0); option; see . + When linking the program, remember to include + M_stub.o in the final link command line, or + you'll get link errors for the missing function(s) (this isn't + necessary when building your program with ghc + ––make, as GHC will automatically link in the + correct bits). + Using your own <literal>main()</literal> @@ -134,18 +245,11 @@ extern HsInt foo(HsInt a0); #include "foo_stub.h" #endif -#ifdef __GLASGOW_HASKELL__ -extern void __stginit_Foo ( void ); -#endif - int main(int argc, char *argv[]) { int i; hs_init(&argc, &argv); -#ifdef __GLASGOW_HASKELL__ - hs_add_root(__stginit_Foo); -#endif for (i = 0; i < 5; i++) { printf("%d\n", foo(2500)); @@ -163,39 +267,51 @@ int main(int argc, char *argv[]) The call to hs_init() initializes GHC's runtime system. Do NOT try to invoke any Haskell functions before calling - hs_init(): strange things will + hs_init(): bad things will undoubtedly happen. - We pass argc and + We pass references to argc and argv to hs_init() so that it can separate out any arguments for the RTS (i.e. those arguments between +RTS...-RTS). - Next, we call - hs_add_rooths_add_root - , a GHC-specific interface which is required to - initialise the Haskell modules in the program. The argument - to hs_add_root should be the name of the - initialization function for the "root" module in your program - - in other words, the module which directly or indirectly - imports all the other Haskell modules in the program. In a - standalone Haskell program the root module is normally - Main, but when you are using Haskell code - from a library it may not be. If your program has multiple - root modules, then you can call - hs_add_root multiple times, one for each - root. The name of the initialization function for module - M is - __stginit_M, and - it may be declared as an external function symbol as in the - code above. + + + + + Character + Replacement + + + + + . + zd + + + _ + zu + + + ` + zq + + + Z + ZZ + + + z + zz + + + + After we've finished invoking our Haskell functions, we - can call hs_exit(), which - terminates the RTS. It runs any outstanding finalizers and - generates any profiling or stats output that might have been - requested. + can call hs_exit(), which terminates the + RTS. There can be multiple calls to hs_init(), but each one should be matched @@ -203,7 +319,8 @@ int main(int argc, char *argv[]) hs_exit()The outermost hs_exit() will actually de-initialise the system. NOTE that currently GHC's runtime cannot reliably - re-initialise after this has happened. + re-initialise after this has happened, + see . . NOTE: when linking the final program, it is normally @@ -214,113 +331,77 @@ int main(int argc, char *argv[]) to the Main Haskell module. - - Using <literal>foreign import ccall "wrapper"</literal> with GHC + + Making a Haskell library that can be called from foreign + code - foreign import - ccall "wrapper"with GHC - + The scenario here is much like in , except that the aim is not to link a complete program, but to + make a library from Haskell code that can be deployed in the same + way that you would deploy a library of C code. - When foreign import ccall "wrapper" is used - in a Haskell module, The C stub file M_stub.c - generated by GHC contains small helper functions used by the code - generated for the imported wrapper, so it must be linked in to the - final program. When linking the program, remember to include - M_stub.o in the final link command line, or - you'll get link errors for the missing function(s) (this isn't - necessary when building your program with ghc - ––make, as GHC will automatically link in the - correct bits). - - - - - Using function headers - - C calls, function headers - - When generating C (using the - directive), one can assist the C compiler in detecting type - errors by using the directive - () to provide - .h files containing function - headers. - - For example, + The main requirement here is that the runtime needs to be + initialized before any Haskell code can be called, so your library + should provide initialisation and deinitialisation entry points, + implemented in C or C++. For example: -#include "HsFFI.h" + HsBool mylib_init(void){ + int argc = ... + char *argv[] = ... -void initialiseEFS (HsInt size); -HsInt terminateEFS (void); -HsForeignObj emptyEFS(void); -HsForeignObj updateEFS (HsForeignObj a, HsInt i, HsInt x); -HsInt lookupEFS (HsForeignObj a, HsInt i); - + // Initialize Haskell runtime + hs_init(&argc, &argv); - The types HsInt, - HsForeignObj etc. are described in the H98 FFI - Addendum. - - Note that this approach is only - essential for returning - floats (or if sizeof(int) != - sizeof(int *) on your architecture) but is a Good - Thing for anyone who cares about writing solid code. You're - crazy not to do it. - - -What if you are importing a module from another package, and -a cross-module inlining exposes a foreign call that needs a supporting -? If the imported module is from the same package as -the module being compiled, you should supply all the -that you supplied when compiling the imported module. If the imported module comes -from another package, you won't necessarily know what the appropriate - options are; but they should be in the package -configuration, which GHC knows about. So if you are building a package, remember -to put all those options into the package configuration. -See the c_includes field in . - + // do any other initialization here and + // return false if there was a problem + return HS_BOOL_TRUE; + } - -It is also possible, according the FFI specification, to put the - option in the foreign import -declaration itself: - - foreign import "foo.h f" f :: Int -> IO Int + void mylib_end(void){ + hs_exit(); + } -When compiling this module, GHC will generate a C file that includes -the specified . However, GHC -disables cross-module inlining for such foreign -calls, because it doesn't transport the -information across module boundaries. (There is no fundamental reason for this; -it was just tiresome to implement. The wrapper, which unboxes the arguments -etc, is still inlined across modules.) So if you want the foreign call itself -to be inlined across modules, use the command-line and package-configuration - mechanism. - - - Finding Header files - - Header files named by the - option or in a foreign import declaration - are searched for using the C compiler's usual search path. - You can add directories to this search path using the - option (see ). - - Note: header files are ignored unless compiling via C. - If you had been compiling your code using the native code - generator (the default) and suddenly switch to compiling via - C, then you can get unexpected errors about missing include - files. Compiling via C is enabled automatically when certain - options are given (eg. and - both enable - ). + The initialisation routine, mylib_init, calls + hs_init() as + normal to initialise the Haskell runtime, and the corresponding + deinitialisation function mylib_end() calls + hs_exit() to shut down the runtime. + + + Using header files + + C calls, function headers + + C functions are normally declared using prototypes in a C + header file. Earlier versions of GHC (6.8.3 and + earlier) #included the header file in + the C source file generated from the Haskell code, and the C + compiler could therefore check that the C function being + called via the FFI was being called at the right type. + + GHC no longer includes external header files when + compiling via C, so this checking is not performed. The + change was made for compatibility with the native code backend + (-fasm) and to comply strictly with the FFI + specification, which requires that FFI calls are not subject + to macro expansion and other CPP conversions that may be + applied when using C header files. This approach also + simplifies the inlining of foreign calls across module and + package boundaries: there's no need for the header file to be + available when compiling an inlined version of a foreign call, + so the compiler is free to inline foreign calls in any + context. + + The -#include option is now + deprecated, and the include-files field + in a Cabal package specification is ignored. + + Memory Allocation @@ -400,12 +481,204 @@ to be inlined across modules, use the command-line and package-configuration + + + Multi-threading and the FFI + + In order to use the FFI in a multi-threaded setting, you must + use the option + (see ). + + + Foreign imports and multi-threading + + When you call a foreign imported + function that is annotated as safe (the + default), and the program was linked + using , then the call will run + concurrently with other running Haskell threads. If the + program was linked without , + then the other Haskell threads will be blocked until the + call returns. + + This means that if you need to make a foreign call to + a function that takes a long time or blocks indefinitely, + then you should mark it safe and + use . Some library functions + make such calls internally; their documentation should + indicate when this is the case. + + If you are making foreign calls from multiple Haskell + threads and using , make sure that + the foreign code you are calling is thread-safe. In + particularly, some GUI libraries are not thread-safe and + require that the caller only invokes GUI methods from a + single thread. If this is the case, you may need to + restrict your GUI operations to a single Haskell thread, + and possibly also use a bound thread (see + ). + + Note that foreign calls made by different Haskell + threads may execute in parallel, even + when the +RTS -N flag is not being used + (). The +RTS + -N flag controls parallel execution of Haskell + threads, but there may be an arbitrary number of foreign + calls in progress at any one time, regardless of + the +RTS -N value. + + If a call is annotated as interruptible + and the program was multithreaded, the call may be + interrupted in the event that the Haskell thread receives an + exception. The mechanism by which the interrupt occurs + is platform dependent, but is intended to cause blocking + system calls to return immediately with an interrupted error + code. The underlying operating system thread is not to be + destroyed. See for more details. + + + + The relationship between Haskell threads and OS + threads + + Normally there is no fixed relationship between Haskell + threads and OS threads. This means that when you make a + foreign call, that call may take place in an unspecified OS + thread. Furthermore, there is no guarantee that multiple + calls made by one Haskell thread will be made by the same OS + thread. + + This usually isn't a problem, and it allows the GHC + runtime system to make efficient use of OS thread resources. + However, there are cases where it is useful to have more + control over which OS thread is used, for example when + calling foreign code that makes use of thread-local state. + For cases like this, we provide bound + threads, which are Haskell threads tied to a + particular OS thread. For information on bound threads, see + the documentation + for the Control.Concurrent + module. + + + + Foreign exports and multi-threading + + When the program is linked + with , then you may + invoke foreign exported functions from + multiple OS threads concurrently. The runtime system must + be initialised as usual by + calling hs_init(), and this call must + complete before invoking any foreign + exported functions. + + + + On the use of <literal>hs_exit()</literal> + + hs_exit() normally causes the termination of + any running Haskell threads in the system, and when + hs_exit() returns, there will be no more Haskell + threads running. The runtime will then shut down the system in an + orderly way, generating profiling + output and statistics if necessary, and freeing all the memory it + owns. + + It isn't always possible to terminate a Haskell thread forcibly: + for example, the thread might be currently executing a foreign call, + and we have no way to force the foreign call to complete. What's + more, the runtime must + assume that in the worst case the Haskell code and runtime are about + to be removed from memory (e.g. if this is a Windows DLL, + hs_exit() is normally called before unloading the + DLL). So hs_exit() must wait + until all outstanding foreign calls return before it can return + itself. + + The upshot of this is that if you have Haskell threads that are + blocked in foreign calls, then hs_exit() may hang + (or possibly busy-wait) until the calls return. Therefore it's a + good idea to make sure you don't have any such threads in the system + when calling hs_exit(). This includes any threads + doing I/O, because I/O may (or may not, depending on the + type of I/O and the platform) be implemented using blocking foreign + calls. + + The GHC runtime treats program exit as a special case, to avoid + the need to wait for blocked threads when a standalone + executable exits. Since the program and all its threads are about to + terminate at the same time that the code is removed from memory, it + isn't necessary to ensure that the threads have exited first. + (Unofficially, if you want to use this fast and loose version of + hs_exit(), then call + shutdownHaskellAndExit() instead). + + + + + Floating point and the FFI + + + The standard C99 fenv.h header + provides operations for inspecting and modifying the state of + the floating point unit. In particular, the rounding mode + used by floating point operations can be changed, and the + exception flags can be tested. + + + + In Haskell, floating-point operations have pure types, and the + evaluation order is unspecified. So strictly speaking, since + the fenv.h functions let you change the + results of, or observe the effects of floating point + operations, use of fenv.h renders the + behaviour of floating-point operations anywhere in the program + undefined. + + + + Having said that, we can document exactly + what GHC does with respect to the floating point state, so + that if you really need to use fenv.h then + you can do so with full knowledge of the pitfalls: + + + + GHC completely ignores the floating-point + environment, the runtime neither modifies nor reads it. + + + + + The floating-point environment is not saved over a + normal thread context-switch. So if you modify the + floating-point state in one thread, those changes may be + visible in other threads. Furthermore, testing the + exception state is not reliable, because a context + switch may change it. If you need to modify or test the + floating point state and use threads, then you must use + bound threads + (Control.Concurrent.forkOS), because + a bound thread has its own OS thread, and OS threads do + save and restore the floating-point state. + + + + + It is safe to modify the floating-point unit state + temporarily during a foreign call, because foreign calls + are never pre-empted by GHC. + + + + +