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. + - - + +