X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fwin32-dlls.sgml;h=488f5bd9c74dc7f51bf305e0edca693bc76329de;hb=fb7a723bfd7650a705cb226e07c5b08b7a8e9279;hp=d32bb748133718f5220a67a3e35249cdcb991818;hpb=57ad929d509b5f1b5c5ad510eb2831163f2071fa;p=ghc-hetmet.git
diff --git a/ghc/docs/users_guide/win32-dlls.sgml b/ghc/docs/users_guide/win32-dlls.sgml
index d32bb74..488f5bd 100644
--- a/ghc/docs/users_guide/win32-dlls.sgml
+++ b/ghc/docs/users_guide/win32-dlls.sgml
@@ -10,6 +10,14 @@ dynamic link libraries (DLLs) containing ghc-compiled code. This
section shows you how to make use of this facility.
+
+Until recently, strip 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
+cured the problem (it was supposedly fixed some years ago).
+
+
+
Linking with DLLs
@@ -22,7 +30,6 @@ command-line, so
-
sh$ cat main.hs
module Main where
@@ -31,21 +38,21 @@ sh$ ghc -o main main.hs
ghc: module version changed to 1; reason: no old .hi file
sh$ strip main.exe
sh$ ls -l main.exe
--rwxr-xr-x 1 544 everyone 6144 May 3 17:11 main.exe*
+-rwxr-xr-x 1 544 everyone 4608 May 3 17:11 main.exe*
sh$ ./main
hello, world!
sh$
-
-will give you a binary as before, but the main.exe generated
-will use the Prelude and RTS DLLs instead.
+will give you a binary as before, but the main.exe
+generated will use the Prelude and RTS DLLs instead of linking them in
+statically.
-6K for a "hello, world" application - not bad, huh? :-)
+4K for a "hello, world" application---not bad, huh? :-)
@@ -73,16 +80,21 @@ option on all the Haskell modules that make up your application.
+Making libraries into DLLs doesn't work on Windows at the
+moment (and is no longer supported); however, all the machinery is
+still there. If you're interested, contact the GHC team. Note that
+building an entire Haskell application as a DLL is still supported
+(it's just inter-DLL Haskell calls that don't work).Creating a Win32 DLL--mk-dll
-Sealing up your Haskell library inside a DLL is quite straightforward;
+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 the following command:
+the DLL by issuing a command of the form:
-sh$ ghc --mk-dll -o HSsuper.dll A.o Super.o B.o libmine.a -lgdi32
+ghc --mk-dll -o foo.dll bar.o baz.o wibble.a -lfooble
@@ -94,6 +106,12 @@ line.
+To create a `static' DLL, i.e. one that does not depend on the GHC DLLs,
+use the when compiling up your Haskell code and
+building the DLL.
+
+
+
A couple of things to notice:
@@ -101,120 +119,200 @@ A couple of things to notice:
-
-When compiling the module A, the code emitted by the compiler
-differs depending on whether or not the functions and data it is
-importing from other Haskell modules correspond to symbols that are
-packaged up in a ghc-compiled DLL. To resolve whether such imports are
-'DLL imports' or not, the following rules are used:
-
+Since DLLs correspond to packages (see ) you need
+to use when compiling modules that
+belong to a DLL if you're going to call them from Haskell. Otherwise, Haskell
+code that calls entry points in that DLL will do so incorrectly, and crash.
+For similar reasons, you can only compile a single module tree into a DLL,
+as startupHaskell needs to be able to call its
+initialisation function, and only takes one such argument (see ). Hence the modules
+you compile into a DLL must have a common root.
+
+
-
-
-If the compiler imports from a module that's in the same directory as
-the one being compiled, it is assumed to not belong to a different DLL
-(or executable) than the module being processed, so none of the
-same-directory imports are considered 'DLL imports'.
+By default, the entry points of all the object files will be exported from
+the DLL when using . Should you want to constrain
+this, you can specify the module definition file to use
+on the command line as follows:
+
+
+ghc --mk-dll -o .... -optdll--def -optdllMyDef.def
+
+See Microsoft documentation for details, but a module definition file
+simply lists what entry points you want to export. Here's one that's
+suitable when building a Haskell COM server DLL:
+
+
+EXPORTS
+ DllCanUnloadNow = DllCanUnloadNow@0
+ DllGetClassObject = DllGetClassObject@12
+ DllRegisterServer = DllRegisterServer@0
+ DllUnregisterServer = DllUnregisterServer@0
+
-
+
-If a directory contains the (probably empty) file
-dLL_ifs.hi, the code corresponding to the interface
-files found in that directory are assumed to live in a DLL
-separate from the one being compiled.
+In addition to creating a DLL, the option also
+creates an import library. The import library name is derived from the
+name of the DLL, as follows:
+
+
+DLL: HScool.dll ==> import lib: libHScool_imp.a
+
-Notice that the first rule takes precedence over this one, so if
-you're compiling a module that imports from a Haskell module whose
-interface file live in the same directory, and that directory
-also contains the file dLL_ifs.hi, the import is still not
-being considered to be a 'DLL import'.
+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.,
+libHSfoo.a and
+libHSfoo_imp.a.
+
+Additionally, when the compiler driver is linking in non-static mode, it
+will rewrite occurrence of on the command line to
+. By doing this for you, switching from
+non-static to static linking is simply a question of adding
+ to your command line.
-
+
+
+
+
+
+
+
+Making DLLs to be called from other languages
-If compiling with the option , the previous rule
-is disabled.
+
+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 Foreign Function
+Interface definition, but it can be tricky to work out how to
+combine this with DLL building, so here's an example:
+
-
-
+
+
+
+
+Use foreign export declarations to export the Haskell
+functions you want to call from the outside. For example,
+
+module Adder where
-So, in short, after having built your Haskell DLL, make sure you
-create the file dLL_ifs.hi in the directory that contains
-its interface files. If you don't, Haskell code that calls upon entry
-points in that DLL, will do so incorrectly, and a crash will result.
-(it is unfortunate that this isn't currently caught at compile-time).
+adder :: Int -> Int -> IO Int -- gratuitous use of IO
+adder x y = return (x+y)
+foreign export stdcall adder :: Int -> Int -> IO Int
+
-
+
-By default, the entry points of all the object files will
-be exported from the DLL when using . Should you want
-to constrain this, you can specify the module definition file
-to use on the command line as follows:
-
+Compile it up:
-sh$ ghc --mk-dll -o .... -optdll--def -optdllMyDef.def
+ghc -c adder.hs -fglasgow-exts
+
+This will produce two files, adder.o and adder_stub.o
+
+
-
-See Microsoft documentation for details, but a module definition file
-simply lists what entry points you want to export. Here's one that's
-suitable when building a Haskell COM server DLL:
-
+
+
+compile up a DllMain() that starts up the Haskell
+RTS---a possible implementation is:
-EXPORTS
- DllCanUnloadNow = DllCanUnloadNow@0
- DllGetClassObject = DllGetClassObject@12
- DllRegisterServer = DllRegisterServer@0
- DllUnregisterServer = DllUnregisterServer@0
+#include <windows.h>
+#include <Rts.h>
+
+EXTFUN(__stginit_Adder);
+
+static char* args[] = { "ghcDll", NULL };
+ /* N.B. argv arrays must end with NULL */
+BOOL
+STDCALL
+DllMain
+ ( HANDLE hModule
+ , DWORD reason
+ , void* reserved
+ )
+{
+ 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;
+}
+Here, Adder 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:
+
+gcc -c dllMain.c
+
+
+
+Construct the DLL:
+
+
+ghc --mk-dll -o adder.dll adder.o adder_stub.o dllMain.o
+
+
+
+
+
-In addition to creating a DLL, the option will also
-create an import library. The import library name is derived from the
-name of the DLL, as follows:
+Start using adder from VBA---here's how I would
+Declare it:
-DLL: HScool.dll ==> import lib: libHScool_imp.a
+Private Declare Function adder Lib "adder.dll" Alias "adder@8"
+ (ByVal x As Long, ByVal y As Long) As Long
+Since this Haskell DLL depends on a couple of the DLLs that come with GHC,
+make sure that they are in scope/visible.
+
-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., libHSfoo.a and libHSfoo_imp.a.
-
-Additionally, when the compiler driver is linking in non-static mode,
-it will rewrite occurrence of on the command line to
-. By doing this for you, switching from non-static
-to static linking is simply a question of adding to
-your command line.
-
+
+Building statically linked DLLs is the same as in the previous section: it
+suffices to add to the commands used to compile up
+the Haskell source and build the DLL.
+
-
-
+
+