X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fffi-chap.sgml;h=99d21a3cc19b23274074faa323bc9920a83d19f7;hb=d28ba8c800901bea01f70c4719278c2a364cf9fc;hp=d3658e62e6f33450f8299d682b499c0672317328;hpb=90bf3139476eeca5f47cfe2f72b78cc64353f4d0;p=ghc-hetmet.git diff --git a/ghc/docs/users_guide/ffi-chap.sgml b/ghc/docs/users_guide/ffi-chap.sgml index d3658e6..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. @@ -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 types The 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 <literal>main()</literal> 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 @@ -273,7 +277,7 @@ It is also possible, according the FFI specification, to put the option in the foreign import declaration itself: - foreign import "#include foo.h f" f :: Int -> IO Int + 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 @@ -287,6 +291,85 @@ to be inlined across modules, use the command-line and package-configuration + + + 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. + + + +