X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fffi-chap.xml;h=97a237876ff69a4d0f865f7faea4b0dedfccc4ff;hb=478e69b303eb2e653a2ebf5c888b5efdfef1fb9d;hp=8928ea8a7f7d5debab0f7f3b1bdc0c28b02b9ebf;hpb=a8e681c1e8aa4bc602714ff61583cd4e969d7187;p=ghc-hetmet.git
diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml
index 8928ea8..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 AddendumThe 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
@@ -67,7 +52,7 @@ the
+
+ 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.
+
+
@@ -137,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 main()
@@ -159,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));
@@ -188,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
@@ -228,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
@@ -239,113 +331,77 @@ int main(int argc, char *argv[])
to the Main Haskell module.
-
- Using foreign import ccall "wrapper" 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
@@ -425,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 hs_exit()
+
+ 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.
+
+
+
+
+