<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
+ Addendum. These extensions are described in <xref linkend="ffi-ghcexts" />, but please note that programs using
these features are not portable. Hence, these features should be
avoided where possible.</para>
</listitem>
documentation; see for example the <literal>Foreign</literal>
module.</para>
- <sect1 id="sec-ffi-ghcexts">
+ <sect1 id="ffi-ghcexts">
<title>GHC extensions to the FFI Addendum</title>
<para>The FFI features that are described in this section are specific to
and <literal>ByteArray#</literal>.</para>
</sect2>
+ <sect2 id="ffi-newtype-io">
+ <title>Newtype wrapping of the IO monad</title>
+ <para>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
+ <literal>newtype</literal>, thus:
+<programlisting>
+ newtype MyIO a = MIO (IO a)
+</programlisting>
+ (A reason for doing so might be to prevent the programmer from
+ calling arbitrary IO procedures in some part of the program.)
+</para>
+<para>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 unnwrapping 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:
+<programlisting>
+ foreign import foo :: Int -> MyIO Int
+ foreign import "dynamic" baz :: (Int -> MyIO Int) -> CInt -> MyIO Int
+</programlisting>
+</para>
+ </sect2>
+
</sect1>
- <sect1 id="sec-ffi-ghc">
+ <sect1 id="ffi-ghc">
<title>Using the FFI with GHC</title>
<para>The following sections also give some hints and tips on the
<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>
+ code above. Note that the symbol name should be transformed
+ according to the Z-encoding:</para>
+
+ <informaltable>
+ <tgroup cols="2" align="left" colsep="1" rowsep="1">
+ <thead>
+ <row>
+ <entry>Character</entry>
+ <entry>Replacement</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>.</literal></entry>
+ <entry><literal>zd</literal></entry>
+ </row>
+ <row>
+ <entry><literal>_</literal></entry>
+ <entry><literal>zu</literal></entry>
+ </row>
+ <row>
+ <entry><literal>`</literal></entry>
+ <entry><literal>zq</literal></entry>
+ </row>
+ <row>
+ <entry><literal>Z</literal></entry>
+ <entry><literal>ZZ</literal></entry>
+ </row>
+ <row>
+ <entry><literal>z</literal></entry>
+ <entry><literal>zz</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
<para>After we've finished invoking our Haskell functions, we
can call <literal>hs_exit()</literal>, which