Merge remote branch 'origin/master'
[ghc-hetmet.git] / docs / users_guide / win32-dlls.xml
index 1589821..44f589a 100644 (file)
@@ -71,7 +71,7 @@ Notice how the "%1" argument is quoted (or not).
   <para>This problem doesn't just affect GHCi, it affects any
   GHC-compiled program that wants to catch console events.  See the
   <ulink
-  url="../libraries/base/GHC-ConsoleHandler.html">GHC.ConsoleHandler</ulink>
+  url="&libraryBaseLocation;/GHC-ConsoleHandler.html">GHC.ConsoleHandler</ulink>
   module.</para>
 </sect1>
 
@@ -209,14 +209,6 @@ make-sessions running under cygwin.
 </title>
 
 <para>
-<emphasis>Making Haskell libraries into DLLs doesn't work on Windows at the
-moment; we hope to re-instate this facility in the future.  Note that
-building an entire Haskell application as a single DLL is still supported: it's
-       just multi-DLL Haskell programs that don't work.  The Windows
-       distribution of GHC contains static libraries only.</emphasis></para>
-
-<!--
-<para>
 <indexterm><primary>Dynamic link libraries, Win32</primary></indexterm>
 <indexterm><primary>DLLs, Win32</primary></indexterm>
 On Win32 platforms, the compiler is capable of both producing and using
@@ -225,6 +217,33 @@ section shows you how to make use of this facility.
 </para>
 
 <para>
+There are two distinct ways in which DLLs can be used:
+<itemizedlist>
+  <listitem>
+    <para>
+      You can turn each Haskell package into a DLL, so that multiple
+      Haskell executables using the same packages can share the DLL files.
+      (As opposed to linking the libraries statically, which in effect
+      creates a new copy of the RTS and all libraries for each executable
+      produced.)
+    </para>
+    <para>
+      That is the same as the dynamic linking on other platforms, and it
+      is described in <xref linkend="using-shared-libs"/>.
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+      You can package up a complete Haskell program as a DLL, to be called
+      by some external (usually non-Haskell) program. This is usually used
+      to implement plugins and the like, and is described below.
+    </para>
+  </listitem>
+</itemizedlist>
+</para>
+
+<!--
+<para>
 Until recently, <command>strip</command> didn't work reliably on DLLs, so you
 should test your version with care, or make sure you have the latest
 binutils. Unfortunately, we don't know exactly which version of binutils
@@ -294,7 +313,7 @@ option on all the Haskell modules that make up your application.
 
 <para>
 <indexterm><primary>Creating a Win32 DLL</primary></indexterm>
-<indexterm><primary>&ndash;&ndash;shared</primary></indexterm>
+<indexterm><primary>&ndash;shared</primary></indexterm>
 Sealing up your Haskell library inside a DLL is straightforward;
 compile up the object files that make up the library, and then build
 the DLL by issuing a command of the form:
@@ -302,12 +321,12 @@ the DLL by issuing a command of the form:
 
 <para>
 <screen>
-ghc &ndash;&ndash;shared -o foo.dll bar.o baz.o wibble.a -lfooble
+ghc &ndash;shared -o foo.dll bar.o baz.o wibble.a -lfooble
 </screen>
 </para>
 
 <para>
-By feeding the ghc compiler driver the option <option>&ndash;&ndash;shared</option>, it
+By feeding the ghc compiler driver the option <option>&ndash;shared</option>, it
 will build a DLL rather than produce an executable. The DLL will
 consist of all the object files and archives given on the command
 line.
@@ -347,12 +366,12 @@ you compile into a DLL must have a common root.
 <listitem>
 <para>
 By default, the entry points of all the object files will be exported from
-the DLL when using <option>&ndash;&ndash;shared</option>. Should you want to constrain
+the DLL when using <option>&ndash;shared</option>. Should you want to constrain
 this, you can specify the <emphasis>module definition file</emphasis> to use
 on the command line as follows:
 
 <screen>
-ghc &ndash;&ndash;shared -o .... MyDef.def
+ghc &ndash;shared -o .... MyDef.def
 </screen>
 
 See Microsoft documentation for details, but a module definition file
@@ -371,7 +390,7 @@ EXPORTS
 
 <listitem>
 <para>
-In addition to creating a DLL, the <option>&ndash;&ndash;shared</option> option also
+In addition to creating a DLL, the <option>&ndash;shared</option> option also
 creates an import library. The import library name is derived from the
 name of the DLL, as follows:
 
@@ -402,227 +421,147 @@ non-static to static linking is simply a question of adding
 <title>Making DLLs to be called from other languages</title>
 
 <para>
-If you want to package up Haskell code to be called from other languages,
-such as Visual Basic or C++, there are some extra things it is useful to
-know.  This is a special case of <xref linkend="ffi-library" />; we'll deal with
-          the DLL-specific issues that arise below.  Here's an example:
+  This section describes how to create DLLs to be called from other languages,
+  such as Visual Basic or C++. This is a special case of
+  <xref linkend="ffi-library" />; we'll deal with the DLL-specific issues that
+  arise below. Here's an example:
 </para>
-
-<itemizedlist>
-
-<listitem>
 <para>
-Use <literal>foreign export</literal> declarations to export the Haskell
-functions you want to call from the outside. For example,
-
+  Use foreign export declarations to export the Haskell functions you want to
+  call from the outside. For example:
+</para>
 <programlisting>
+-- Adder.hs
+{-# LANGUAGE ForeignFunctionInterface #-}
 module Adder where
 
-adder :: Int -> Int -> IO Int  &ndash;&ndash; gratuitous use of IO
+adder :: Int -> Int -> IO Int  -- gratuitous use of IO
 adder x y = return (x+y)
 
 foreign export stdcall adder :: Int -> Int -> IO Int
 </programlisting>
-</para>
-</listitem>
-
-<listitem>
 <para>
-Compile it up:
-
-<screen>
-ghc -c adder.hs -fglasgow-exts
-</screen>
-  
-This will produce two files, adder.o and adder_stub.o
+  Add some helper code that starts up and shuts down the Haskell RTS:
 </para>
-</listitem>
-
-<listitem>
-<para>
-compile up a <function>DllMain()</function> that starts up the Haskell
-RTS-&ndash;&ndash;a possible implementation is:
-
 <programlisting>
-#include &lt;windows.h&gt;
+// StartEnd.c
 #include &lt;Rts.h&gt;
 
-extern void __stginit_Adder(void);
-
-static char* args[] = { "ghcDll", NULL };
-                       /* N.B. argv arrays must end with NULL */
-BOOL
-STDCALL
-DllMain
-   ( HANDLE hModule
-   , DWORD reason
-   , void* reserved
-   )
+void HsStart()
 {
-  if (reason == DLL_PROCESS_ATTACH) {
-      /* By now, the RTS DLL should have been hoisted in, but we need to start it up. */
-      startupHaskell(1, args, __stginit_Adder);
-      return TRUE;
-  }
-  return TRUE;
-}
-</programlisting>
-
-Here, <literal>Adder</literal> is the name of the root module in the module
-tree (as mentioned above, there must be a single root module, and hence a
-single module tree in the DLL).
-
-Compile this up:
+   int argc = 1;
+   char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
 
-<screen>
-ghc -c dllMain.c
-</screen>
-</para>
-</listitem>
+   // Initialize Haskell runtime
+   char** args = argv;
+   hs_init(&amp;argc, &amp;args);
+}
 
-<listitem>
+void HsEnd()
+{
+   hs_exit();
+}
+</programlisting>
 <para>
-Construct the DLL:
-
+  Here, <literal>Adder</literal> is the name of the root module in the module
+  tree (as mentioned above, there must be a single root module, and hence a
+  single module tree in the DLL). Compile everything up:
+</para>
 <screen>
-ghc &ndash;&ndash;shared -o adder.dll adder.o adder_stub.o dllMain.o
+ghc -c Adder.hs
+ghc -c StartEnd.c
+ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o
 </screen>
-
-</para>
-</listitem>
-
-<listitem>
 <para>
-Start using <function>adder</function> from VBA-&ndash;&ndash;here's how I would
-<constant>Declare</constant> it:
-
-<programlisting>
-Private Declare Function adder Lib "adder.dll" Alias "adder@8"
-      (ByVal x As Long, ByVal y As Long) As Long
-</programlisting>
-
-Since this Haskell DLL depends on a couple of the DLLs that come with GHC,
-make sure that they are in scope/visible.
+  Now the file <filename>Adder.dll</filename> can be used from other
+  programming languages. Before calling any functions in Adder it is necessary
+  to call <literal>HsStart</literal>, and at the very end call
+  <literal>HsEnd</literal>.
 </para>
-
 <para>
-Building statically linked DLLs is the same as in the previous section: it
-suffices to add <option>-static</option> to the commands used to compile up
-the Haskell source and build the DLL.
+  <emphasis>Warning:</emphasis> It may appear tempting to use
+  <literal>DllMain</literal> to call
+  <literal>hs_init</literal>/<literal>hs_exit</literal>, but this won't work
+  (particularly if you compile with <literal>-threaded</literal>). There are
+  severe restrictions on which actions can be performed during
+  <literal>DllMain</literal>, and <literal>hs_init</literal> violates these
+  restrictions, which can lead to your dll freezing during startup (see
+  <ulink url="http://hackage.haskell.org/trac/ghc/ticket/3605">bug
+  #3605</ulink>).
 </para>
 
-</listitem>
-
-</itemizedlist>
-
-</sect2>
-
-<sect2>
-<title>Beware of DllMain()!</title>
-
-<para>The body of a <literal>DllMain()</literal> function is an
-extremely dangerous place! This is because the order in which DLLs are
-unloaded when a process is terminating is unspecified. This means that
-the <literal>DllMain()</literal> for your DLL may be called when other DLLs containing
-functions that you call when de-initializing your DLL have already
-been unloaded. In other words, you can't put shutdown code inside
-<literal>DllMain()</literal>, unless your shutdown code only requires use of certain
-functions which are guaranteed to be available (see the Platform SDK
-docs for more info).</para>
-
-<para>In particular, if you are writing a DLL that's statically
-linked with Haskell, it is not safe to call
-<literal>hs_exit()</literal> from <literal>DllMain()</literal>, since
-<literal>hs_exit()</literal> may make use of other DLLs (see also <xref
-          linkend="hs-exit" />).  What's more, if you
-wait until program shutdown to execute your deinitialisation code, Windows will have
-terminated all the threads in your program except the one calling
-<literal>DllMain()</literal>, which can cause even more
-problems.</para>
-
-<para>A solution is to always export <literal>Begin()</literal> and <literal>End()</literal> functions from your
-DLL, and call these from the application that uses the DLL, so that
-you can be sure that all DLLs needed by any shutdown code in your
-End() function are available when it is called.</para>
-
-<para>The following example is untested but illustrates the idea (please let us
-        know if you find problems with this example or have a better one).  Suppose we have a DLL called Lewis which makes use of 2
-Haskell modules <literal>Bar</literal> and <literal>Zap</literal>,
-where <literal>Bar</literal> imports <literal>Zap</literal> and is
-therefore the root module in the sense of <xref
-linkend="using-own-main" />. Then the main C++ unit for the DLL would
-look something like:</para>
+<sect3 id="win32-dlls-vba">
+<title>Using from VBA</title>
 
+<para>
+  An example of using <filename>Adder.dll</filename> from VBA is:
+</para>
 <programlisting>
- // Lewis.cpp -- compiled using GCC
- #include &lt;Windows.h&gt;
- #include "HsFFI.h"
-
- #define __LEWIS_DLL_EXPORT
- #include "Lewis.h"
-
- #include "Bar_stub.h"  // generated by GHC
- #include "Zap_stub.h"
-
- BOOL APIENTRY DllMain( HANDLE hModule, 
-                        DWORD  ul_reason_for_call, 
-                        LPVOID lpReserved
-                       ){
-   return TRUE;
- }
-
- extern "C"{
-
- LEWIS_API HsBool lewis_Begin(){
-   int argc = ...
-   char *argv[] = ...
-
-   // Initialize Haskell runtime
-   hs_init(&amp;argc, &amp;argv);
-
-   // Tell Haskell about all root modules
-   hs_add_root(__stginit_Bar);
+Private Declare Function Adder Lib "Adder.dll" Alias "adder@8" _
+      (ByVal x As Long, ByVal y As Long) As Long
 
-   // do any other initialization here and
-   // return false if there was a problem
-   return HS_BOOL_TRUE;
- }
+Private Declare Sub HsStart Lib "Adder.dll" ()
+Private Declare Sub HsEnd Lib "Adder.dll" ()
 
- LEWIS_API void lewis_End(){
-   hs_exit();
- }
+Private Sub Document_Close()
+HsEnd
+End Sub
 
- LEWIS_API HsInt lewis_Test(HsInt x){
-   // use Haskell functions exported by
-   // modules Bar and/or Zap
+Private Sub Document_Open()
+HsStart
+End Sub
 
-   return ...
- }
-
- } // extern "C"
+Public Sub Test()
+MsgBox "12 + 5 = " &amp; Adder(12, 5)
+End Sub
+</programlisting>
+<para>
+  This example uses the
+  <literal>Document_Open</literal>/<literal>Close</literal> functions of
+  Microsoft Word, but provided <literal>HsStart</literal> is called before the
+  first function, and <literal>HsEnd</literal> after the last, then it will
+  work fine.
+</para>
+</sect3>
 
-and some application which used the functions in the DLL would have a main() function like:
+<sect3 id="win32-dlls-c++">
+<title>Using from C++</title>
 
- // MyApp.cpp
- #include "stdafx.h"
- #include "Lewis.h"
+<para>
+  An example of using <filename>Adder.dll</filename> from C++ is:
+</para>
 
- int main(int argc, char *argv[]){
-   if (lewis_Begin()){
-      // can now safely call other functions
-      // exported by Lewis DLL
+<programlisting>
+// Tester.cpp
+#include "HsFFI.h"
+#include "Adder_stub.h"
+#include &lt;stdio.h&gt;
+
+extern "C" {
+    void HsStart();
+    void HsEnd();
+}
 
-   }
-   lewis_End();
-   return 0;
- }
+int main()
+{
+    HsStart();
+    // can now safely call functions from the DLL
+    printf("12 + 5 = %i\n", adder(12,5))    ;
+    HsEnd();
+    return 0;
+}
 </programlisting>
-
-<para><literal>Lewis.h</literal> would have to have some appropriate <literal>#ifndef</literal> to ensure that the
-Haskell FFI types were defined for external users of the DLL (who
-wouldn't necessarily have GHC installed and therefore wouldn't have
-the include files like <literal>HsFFI.h</literal> etc). 
+<para>
+  This can be compiled and run with:
 </para>
+<screen>
+$ ghc -o tester Tester.cpp Adder.dll.a
+$ tester
+12 + 5 = 17
+</screen>
+
+</sect3>
+
 </sect2>
 
 </sect1>
@@ -630,7 +569,6 @@ the include files like <literal>HsFFI.h</literal> etc).
 
 <!-- Emacs stuff:
      ;;; Local Variables: ***
-     ;;; mode: xml ***
      ;;; sgml-parent-document: ("users_guide.xml" "book" "chapter") ***
      ;;; End: ***
  -->