diff options
Diffstat (limited to 'docs/users_guide/ffi-chap.xml')
-rw-r--r-- | docs/users_guide/ffi-chap.xml | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/docs/users_guide/ffi-chap.xml b/docs/users_guide/ffi-chap.xml new file mode 100644 index 0000000000..e1374c4610 --- /dev/null +++ b/docs/users_guide/ffi-chap.xml @@ -0,0 +1,411 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!-- FFI docs as a chapter --> + +<chapter id="ffi"> + <title> +Foreign function interface (FFI) + </title> + + <para>GHC (mostly) conforms to the Haskell 98 Foreign Function Interface + Addendum 1.0, whose definition is available from <ulink url="http://haskell.org/"><literal>http://haskell.org/</literal></ulink>.</para> + + <para>To enable FFI support in GHC, give the <option>-fffi</option><indexterm><primary><option>-fffi</option></primary> + </indexterm>flag, or +the <option>-fglasgow-exts</option><indexterm><primary><option>-fglasgow-exts</option></primary> + </indexterm> flag which implies <option>-fffi</option> +.</para> + + <para>The FFI support in GHC diverges from the Addendum in the following ways:</para> + + <itemizedlist> + <listitem> + <para>Syntactic forms and library functions proposed in earlier versions + of the FFI are still supported for backwards compatibility.</para> + </listitem> + + <listitem> + <para>GHC implements a number of GHC-specific extensions to the FFI + Addendum. These extensions are described in <xref linkend="sec-ffi-ghcexts" />, but please note that programs using + these features are not portable. Hence, these features should be + avoided where possible.</para> + </listitem> + </itemizedlist> + + <para>The FFI libraries are documented in the accompanying library + documentation; see for example the <literal>Foreign</literal> + module.</para> + + <sect1 id="sec-ffi-ghcexts"> + <title>GHC extensions to the FFI Addendum</title> + + <para>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.</para> + + <sect2> + <title>Unboxed types</title> + + <para>The following unboxed types may be used as basic foreign types + (see FFI Addendum, Section 3.2): <literal>Int#</literal>, + <literal>Word#</literal>, <literal>Char#</literal>, + <literal>Float#</literal>, <literal>Double#</literal>, + <literal>Addr#</literal>, <literal>StablePtr# a</literal>, + <literal>MutableByteArray#</literal>, <literal>ForeignObj#</literal>, + and <literal>ByteArray#</literal>.</para> + </sect2> + + </sect1> + + <sect1 id="sec-ffi-ghc"> + <title>Using the FFI with GHC</title> + + <para>The following sections also give some hints and tips on the + use of the foreign function interface in GHC.</para> + + <sect2 id="foreign-export-ghc"> + <title>Using <literal>foreign export</literal> and <literal>foreign import ccall "wrapper"</literal> with GHC</title> + + <indexterm><primary><literal>foreign export + </literal></primary><secondary>with GHC</secondary> + </indexterm> + + <para>When GHC compiles a module (say <filename>M.hs</filename>) + which uses <literal>foreign export</literal> or + <literal>foreign import "wrapper"</literal>, it generates two + additional files, <filename>M_stub.c</filename> and + <filename>M_stub.h</filename>. GHC will automatically compile + <filename>M_stub.c</filename> to generate + <filename>M_stub.o</filename> at the same time.</para> + + <para>For a plain <literal>foreign export</literal>, the file + <filename>M_stub.h</filename> contains a C prototype for the + foreign exported function, and <filename>M_stub.c</filename> + contains its definition. For example, if we compile the + following module:</para> + +<programlisting> +module Foo where + +foreign export ccall foo :: Int -> IO Int + +foo :: Int -> IO Int +foo n = return (length (f n)) + +f :: Int -> [Int] +f 0 = [] +f n = n:(f (n-1))</programlisting> + + <para>Then <filename>Foo_stub.h</filename> will contain + something like this:</para> + +<programlisting> +#include "HsFFI.h" +extern HsInt foo(HsInt a0);</programlisting> + + <para>and <filename>Foo_stub.c</filename> contains the + compiler-generated definition of <literal>foo()</literal>. To + invoke <literal>foo()</literal> from C, just <literal>#include + "Foo_stub.h"</literal> and call <literal>foo()</literal>.</para> + + <para>The <filename>foo_stub.c</filename> and + <filename>foo_stub.h</filename> files can be redirected using the + <option>-stubdir</option> option; see <xref linkend="options-output" + />.</para> + + <sect3 id="using-own-main"> + <title>Using your own <literal>main()</literal></title> + + <para>Normally, GHC's runtime system provides a + <literal>main()</literal>, which arranges to invoke + <literal>Main.main</literal> in the Haskell program. However, + you might want to link some Haskell code into a program which + has a main function written in another language, say C. In + order to do this, you have to initialize the Haskell runtime + system explicitly.</para> + + <para>Let's take the example from above, and invoke it from a + standalone C program. Here's the C code:</para> + +<programlisting> +#include <stdio.h> +#include "HsFFI.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; + + hs_init(&argc, &argv); +#ifdef __GLASGOW_HASKELL__ + hs_add_root(__stginit_Foo); +#endif + + for (i = 0; i < 5; i++) { + printf("%d\n", foo(2500)); + } + + hs_exit(); + return 0; +}</programlisting> + + <para>We've surrounded the GHC-specific bits with + <literal>#ifdef __GLASGOW_HASKELL__</literal>; the rest of the + code should be portable across Haskell implementations that + support the FFI standard.</para> + + <para>The call to <literal>hs_init()</literal> + initializes GHC's runtime system. Do NOT try to invoke any + Haskell functions before calling + <literal>hs_init()</literal>: strange things will + undoubtedly happen.</para> + + <para>We pass <literal>argc</literal> and + <literal>argv</literal> to <literal>hs_init()</literal> + so that it can separate out any arguments for the RTS + (i.e. those arguments between + <literal>+RTS...-RTS</literal>).</para> + + <para>Next, we call + <function>hs_add_root</function><indexterm><primary><function>hs_add_root</function></primary> + </indexterm>, a GHC-specific interface which is required to + initialise the Haskell modules in the program. The argument + to <function>hs_add_root</function> 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 + <literal>Main</literal>, 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 + <function>hs_add_root</function> multiple times, one for each + root. The name of the initialization function for module + <replaceable>M</replaceable> is + <literal>__stginit_<replaceable>M</replaceable></literal>, and + it may be declared as an external function symbol as in the + code above.</para> + + <para>After we've finished invoking our Haskell functions, we + can call <literal>hs_exit()</literal>, which + terminates the RTS. It runs any outstanding finalizers and + generates any profiling or stats output that might have been + requested.</para> + + <para>There can be multiple calls to + <literal>hs_init()</literal>, but each one should be matched + by one (and only one) call to + <literal>hs_exit()</literal><footnote><para>The outermost + <literal>hs_exit()</literal> will actually de-initialise the + system. NOTE that currently GHC's runtime cannot reliably + re-initialise after this has happened.</para> + </footnote>.</para> + + <para>NOTE: when linking the final program, it is normally + easiest to do the link using GHC, although this isn't + essential. If you do use GHC, then don't forget the flag + <option>-no-hs-main</option><indexterm><primary><option>-no-hs-main</option></primary> + </indexterm>, otherwise GHC will try to link + to the <literal>Main</literal> Haskell module.</para> + </sect3> + + <sect3 id="foreign-export-dynamic-ghc"> + <title>Using <literal>foreign import ccall "wrapper"</literal> with GHC</title> + + <indexterm><primary><literal>foreign import + ccall "wrapper"</literal></primary><secondary>with GHC</secondary> + </indexterm> + + <para>When <literal>foreign import ccall "wrapper"</literal> is used + in a Haskell module, The C stub file <filename>M_stub.c</filename> + 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 + <filename>M_stub.o</filename> 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 <literal>ghc + ––make</literal>, as GHC will automatically link in the + correct bits).</para> + </sect3> + </sect2> + + <sect2 id="glasgow-foreign-headers"> + <title>Using function headers</title> + + <indexterm><primary>C calls, function headers</primary></indexterm> + + <para>When generating C (using the <option>-fvia-C</option> + directive), one can assist the C compiler in detecting type + errors by using the <option>-#include</option> directive + (<xref linkend="options-C-compiler"/>) to provide + <filename>.h</filename> files containing function + headers.</para> + + <para>For example,</para> + +<programlisting> +#include "HsFFI.h" + +void initialiseEFS (HsInt size); +HsInt terminateEFS (void); +HsForeignObj emptyEFS(void); +HsForeignObj updateEFS (HsForeignObj a, HsInt i, HsInt x); +HsInt lookupEFS (HsForeignObj a, HsInt i); +</programlisting> + + <para>The types <literal>HsInt</literal>, + <literal>HsForeignObj</literal> etc. are described in the H98 FFI + Addendum.</para> + + <para>Note that this approach is only + <emphasis>essential</emphasis> for returning + <literal>float</literal>s (or if <literal>sizeof(int) != + sizeof(int *)</literal> on your architecture) but is a Good + Thing for anyone who cares about writing solid code. You're + crazy not to do it.</para> + +<para> +What if you are importing a module from another package, and +a cross-module inlining exposes a foreign call that needs a supporting +<option>-#include</option>? If the imported module is from the same package as +the module being compiled, you should supply all the <option>-#include</option> +that you supplied when compiling the imported module. If the imported module comes +from another package, you won't necessarily know what the appropriate +<option>-#include</option> 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 <option>-#include</option> options into the package configuration. +See the <literal>c_includes</literal> field in <xref linkend="package-management"/>. +</para> + +<para> +It is also possible, according the FFI specification, to put the +<option>-#include</option> option in the foreign import +declaration itself: +<programlisting> + foreign import "foo.h f" f :: Int -> IO Int +</programlisting> +When compiling this module, GHC will generate a C file that includes +the specified <option>-#include</option>. However, GHC +<emphasis>disables</emphasis> cross-module inlining for such foreign +calls, because it doesn't transport the <option>-#include</option> +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 +<option>-#include</option> mechanism. +</para> + + <sect3 id="finding-header-files"> + <title>Finding Header files</title> + + <para>Header files named by the <option>-#include</option> + option or in a <literal>foreign import</literal> declaration + are searched for using the C compiler's usual search path. + You can add directories to this search path using the + <option>-I</option> option (see <xref + linkend="c-pre-processor"/>).</para> + + <para>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. <option>-O</option> and + <option>-prof</option> both enable + <option>-fvia-C</option>).</para> + </sect3> + + </sect2> + + <sect2> + <title>Memory Allocation</title> + + <para>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.</para> + + <variablelist> + <varlistentry> + <term><literal>alloca</literal> and friends</term> + <listitem> + <para>Useful for short-term allocation when the allocation + is intended to scope over a given <literal>IO</literal> + computation. This kind of allocation is commonly used + when marshalling data to and from FFI functions.</para> + + <para>In GHC, <literal>alloca</literal> is implemented + using <literal>MutableByteArray#</literal>, so allocation + and deallocation are fast: much faster than C's + <literal>malloc/free</literal>, but not quite as fast as + stack allocation in C. Use <literal>alloca</literal> + whenever you can.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>mallocForeignPtr</literal></term> + <listitem> + <para>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 + <literal>mallocForeignPtr</literal> is + <emphasis>not</emphasis> a good choice, however.</para> + + <para>In GHC, <literal>mallocForeignPtr</literal> is also + implemented using <literal>MutableByteArray#</literal>. + Although the memory is pointed to by a + <literal>ForeignPtr</literal>, there are no actual + finalizers involved (unless you add one with + <literal>addForeignPtrFinalizer</literal>), and the + deallocation is done using GC, so + <literal>mallocForeignPtr</literal> is normally very + cheap.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>malloc/free</literal></term> + <listitem> + <para>If all else fails, then you need to resort to + <literal>Foreign.malloc</literal> and + <literal>Foreign.free</literal>. These are just wrappers + around the C functions 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 <literal>malloc</literal> and + <literal>free</literal> to be significantly slower than + the other forms of allocation above.</para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>Foreign.Marshal.Pool</literal></term> + <listitem> + <para>Pools are currently implemented using + <literal>malloc/free</literal>, 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 implementation of Pools in the + future, however.</para> + </listitem> + </varlistentry> + </variablelist> + </sect2> + </sect1> +</chapter> + +<!-- Emacs stuff: + ;;; Local Variables: *** + ;;; mode: xml *** + ;;; sgml-parent-document: ("users_guide.xml" "book" "chapter") *** + ;;; End: *** + --> |