FIX #1861: floating-point constants for infinity and NaN in via-C
[ghc-hetmet.git] / docs / users_guide / win32-dlls.xml
index 22a77de..703bb18 100644 (file)
@@ -210,8 +210,7 @@ make-sessions running under cygwin.
 
 <para>
 <emphasis>Making Haskell libraries into DLLs doesn't work on Windows at the
-moment; however, all the machinery is
-still there. If you're interested, contact the GHC team. Note that
+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>
@@ -295,7 +294,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;mk-dll</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:
@@ -303,12 +302,12 @@ the DLL by issuing a command of the form:
 
 <para>
 <screen>
-ghc &ndash;&ndash;mk-dll -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;mk-dll</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.
@@ -348,12 +347,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;mk-dll</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;mk-dll -o .... -optdll&ndash;&ndash;def -optdllMyDef.def
+ghc &ndash;shared -o .... MyDef.def
 </screen>
 
 See Microsoft documentation for details, but a module definition file
@@ -372,22 +371,22 @@ EXPORTS
 
 <listitem>
 <para>
-In addition to creating a DLL, the <option>&ndash;&ndash;mk-dll</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:
 
 <programlisting>
-DLL: HScool.dll  ==&#62; import lib: libHScool_imp.a
+DLL: HScool.dll  ==&#62; import lib: libHScool.dll.a
 </programlisting>
 
 The naming scheme may look a bit weird, but it has the purpose of allowing
 the co-existence of import libraries with ordinary static libraries (e.g.,
 <filename>libHSfoo.a</filename> and
-<filename>libHSfoo&lowbar;imp.a</filename>.
+<filename>libHSfoo.dll.a</filename>.
 
 Additionally, when the compiler driver is linking in non-static mode, it
 will rewrite occurrence of <option>-lHSfoo</option> on the command line to
-<option>-lHSfoo&lowbar;imp</option>. By doing this for you, switching from
+<option>-lHSfoo.dll</option>. By doing this for you, switching from
 non-static to static linking is simply a question of adding
 <option>-static</option> to your command line.
 
@@ -403,13 +402,10 @@ 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. The dirty details are in the <emphasis>Foreign Function
-Interface</emphasis> definition, but it can be tricky to work out how to
-combine this with DLL building, so here's an example:
-
+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:
 </para>
 
 <itemizedlist>
@@ -451,7 +447,7 @@ RTS-&ndash;&ndash;a possible implementation is:
 #include &lt;windows.h&gt;
 #include &lt;Rts.h&gt;
 
-extern void__stginit_Adder(void);
+extern void __stginit_Adder(void);
 
 static char* args[] = { "ghcDll", NULL };
                        /* N.B. argv arrays must end with NULL */
@@ -489,7 +485,7 @@ ghc -c dllMain.c
 Construct the DLL:
 
 <screen>
-ghc &ndash;&ndash;mk-dll -o adder.dll adder.o adder_stub.o dllMain.o
+ghc &ndash;shared -o adder.dll adder.o adder_stub.o dllMain.o
 </screen>
 
 </para>
@@ -521,6 +517,114 @@ the Haskell source and build the DLL.
 
 </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>
+
+<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);
+
+   // do any other initialization here and
+   // return false if there was a problem
+   return HS_BOOL_TRUE;
+ }
+
+ LEWIS_API void lewis_End(){
+   hs_exit();
+ }
+
+ LEWIS_API HsInt lewis_Test(HsInt x){
+   // use Haskell functions exported by
+   // modules Bar and/or Zap
+
+   return ...
+ }
+
+ } // extern "C"
+
+and some application which used the functions in the DLL would have a main() function like:
+
+ // MyApp.cpp
+ #include "stdafx.h"
+ #include "Lewis.h"
+
+ int main(int argc, char *argv[]){
+   if (lewis_Begin()){
+      // can now safely call other functions
+      // exported by Lewis DLL
+
+   }
+   lewis_End();
+   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>
+</sect2>
+
 </sect1>
 </chapter>