X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fffi-chap.sgml;h=99d21a3cc19b23274074faa323bc9920a83d19f7;hb=d28ba8c800901bea01f70c4719278c2a364cf9fc;hp=9009a509f4c12dababc95210b143085b971b5355;hpb=de1d4a16d94fa13e9d40a1ac755eae6249595e66;p=ghc-hetmet.git
diff --git a/ghc/docs/users_guide/ffi-chap.sgml b/ghc/docs/users_guide/ffi-chap.sgml
index 9009a50..99d21a3 100644
--- a/ghc/docs/users_guide/ffi-chap.sgml
+++ b/ghc/docs/users_guide/ffi-chap.sgml
@@ -11,12 +11,6 @@
- The routines hs_init(),
- hs_exit(), and hs_set_argv() from
- Chapter 6.1 of the Addendum are not supported yet.
-
-
- Syntactic forms and library functions proposed in earlier versions
of the FFI are still supported for backwards compatibility.
@@ -30,9 +24,9 @@
- The FFI libraries are documented in .
-
+ The FFI libraries are documented in the accompanying library
+ documentation; see for example the Foreign
+ module.GHC extensions to the FFI Addendum
@@ -42,15 +36,6 @@
resulting code.
- Arrays
-
- The types ByteArray and
- MutableByteArray may be used as basic foreign types
- (see FFI Addendum, Section 3.2). In C land, they map to
- (char *).
-
-
- Unboxed typesThe following unboxed types may be used as basic foreign types
@@ -116,7 +101,7 @@ extern HsInt foo(HsInt a0);
invoke foo() from C, just #include
"Foo_stub.h" and call foo().
-
+ Using your own main()Normally, GHC's runtime system provides a
@@ -132,64 +117,83 @@ extern HsInt foo(HsInt a0);
#include <stdio.h>
-#include "foo_stub.h"
+#include "HsFFI.h"
-#include "RtsAPI.h"
+#ifdef __GLASGOW_HASKELL__
+#include "foo_stub.h"
+#endif
+#ifdef __GLASGOW_HASKELL__
extern void __stginit_Foo ( void );
+#endif
int main(int argc, char *argv[])
{
int i;
- startupHaskell(argc, argv, __stginit_Foo);
+ hs_init(&argc, &argv);
+#ifdef __GLASGOW_HASKELL__
+ hs_add_root(__stginit_Foo);
+#endif
for (i = 0; i < 5; i++) {
printf("%d\n", foo(2500));
}
- shutdownHaskell();
-
+ hs_exit();
return 0;
}
- The call to startupHaskell()
+ We've surrounded the GHC-specific bits with
+ #ifdef __GLASGOW_HASKELL__; the rest of the
+ code should be portable across Haskell implementations that
+ support the FFI standard.
+
+ The call to hs_init()
initializes GHC's runtime system. Do NOT try to invoke any
Haskell functions before calling
- startupHaskell(): strange things will
+ hs_init(): strange things will
undoubtedly happen.We pass argc and
- argv to startupHaskell()
+ argv to hs_init()
so that it can separate out any arguments for the RTS
(i.e. those arguments between
+RTS...-RTS).
- The third argument to startupHaskell()
- is used for initializing the Haskell modules in the program.
- It must be the name of the initialization function for the
- "top" module in the program/library - in other words, the
- module which directly or indirectly imports all the other
- Haskell modules in the program. In a standalone Haskell
- program this would be module Main, but when
- you are only using the Haskell code as a library it may not
- be. If your library doesn't have such a module, then it is
- straightforward to create one, purely for this initialization
- process. The name of the initialization function for module
+ 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.After we've finished invoking our Haskell functions, we
- can call shutdownHaskell(), which
+ 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.
- The functions startupHaskell() and
- shutdownHaskell() may be called only once
- each, and only in that order.
+ There can be multiple calls to
+ hs_init(), but each one should be matched
+ by one (and only one) call to
+ 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.
+ .NOTE: when linking the final program, it is normally
easiest to do the link using GHC, although this isn't
@@ -226,7 +230,6 @@ int main(int argc, char *argv[])
C calls, function headersWhen generating C (using the
-
directive), one can assist the C compiler in detecting type
errors by using the directive
() to provide
@@ -256,6 +259,116 @@ HsInt lookupEFS (HsForeignObj a, HsInt i);
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 .
+
+
+
+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
+
+When compiling this module, GHC will generate a C file that includes
+the specified . However, GHC
+disables cross-module inlinding 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.
+
+
+
+
+
+ Memory Allocation
+
+ The FFI libraries provide several ways to allocate memory
+ for use with the FFI, and it isn't always clear which way is the
+ best. This decision may be affected by how efficient a
+ particular kind of allocation is on a given compiler/platform,
+ so this section aims to shed some light on how the different
+ kinds of allocation perform with GHC.
+
+
+
+ alloca and friends
+
+ Useful for short-term allocation when the allocation
+ is intended to scope over a given IO
+ compuatation. This kind of allocation is commonly used
+ when marshalling data to and from FFI functions.
+
+ In GHC, alloca is implemented
+ using MutableByteArray#, so allocation
+ and deallocation are fast: much faster than C's
+ malloc/free, but not quite as fast as
+ stack allocation in C. Use alloca
+ whenever you can.
+
+
+
+
+ mallocForeignPtr
+
+ Useful for longer-term allocation which requires
+ garbage collection. If you intend to store the pointer to
+ the memory in a foreign data structure, then
+ mallocForeignPtr is
+ not a good choice, however.
+
+ In GHC, mallocForeignPtr is also
+ implemented using MutableByteArray#.
+ Although the memory is pointed to by a
+ ForeignPtr, there are no actual
+ finalizers involved (unless you add one with
+ addForeignPtrFinalizer), and the
+ deallocation is done using GC, so
+ mallocForeignPtr is normally very
+ cheap.
+
+
+
+
+ malloc/free
+
+ If all else fails, then you need to resort to
+ Foreign.malloc and
+ Foreign.free. These are just wrappers
+ around the C funcitons of the same name, and their
+ efficiency will depend ultimately on the implementations
+ of these functions in your platform's C library. We
+ usually find malloc and
+ free to be significantly slower than
+ the other forms of allocation above.
+
+
+
+
+ Foreign.Marhsal.Pool
+
+ Pools are currently implemented using
+ malloc/free, so while they might be a
+ more convenient way to structure your memory allocation
+ than using one of the other forms of allocation, they
+ won't be any more efficient. We do plan to provide an
+ improved-performance implementaiton of Pools in the
+ future, however.
+
+
+