X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fwin32-dlls.xml;h=bf243a2cd1c780eb56a1f39656503e2f84420cb8;hb=12f7b86504e94e3507e9e51cb27b14c049d943f8;hp=959f7ce1b65f67a1c9690343c1e5c8d45e95682f;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/docs/users_guide/win32-dlls.xml b/docs/users_guide/win32-dlls.xml index 959f7ce..bf243a2 100644 --- a/docs/users_guide/win32-dlls.xml +++ b/docs/users_guide/win32-dlls.xml @@ -2,9 +2,9 @@ Running GHC on Win32 systems - + -Starting GHC on Win32 platforms +Starting GHC on Windows platforms The installer that installs GHC on Win32 also sets up the file-suffix associations @@ -36,7 +36,46 @@ Notice how the "%1" argument is quoted (or not). - + +Running GHCi on Windows + + We recommend running GHCi in a standard Windows console: + select the GHCi option from the start menu item + added by the GHC installer, or use + Start->Run->cmd to get a Windows console and + invoke ghci from there (as long as it's in your + PATH). + + If you run GHCi in a Cygwin or MSYS shell, then the Control-C + behaviour is adversely affected. In one of these environments you + should use the ghcii.sh script to start GHCi, + otherwise when you hit Control-C you'll be returned to the shell + prompt but the GHCi process will still be running. However, even + using the ghcii.sh script, if you hit Control-C + then the GHCi process will be killed immediately, rather than + letting you interrupt a running program inside GHCi as it should. + This problem is caused by the fact that the Cygwin and MSYS shell + environments don't pass Control-C events to non-Cygwin child + processes, because in order to do that there needs to be a Windows + console. + + There's an exception: you can use a Cygwin shell if the + CYGWIN environment variable does + not contain tty. In this + mode, the Cygwin shell behaves like a Windows console shell and + console events are propagated to child processes. Note that the + CYGWIN environment variable must be set + before starting the Cygwin shell; changing it + afterwards has no effect on the shell. + + This problem doesn't just affect GHCi, it affects any + GHC-compiled program that wants to catch console events. See the + GHC.ConsoleHandler + module. + + + Interacting with the terminal @@ -63,7 +102,7 @@ You can get a close simulation by using an emacs shell buffer! - + Differences in library behaviour @@ -86,7 +125,7 @@ binary mode using IOExts.hSetBinaryMode. The - + Using GHC (and other GHC-compiled executables) with cygwin @@ -171,8 +210,8 @@ make-sessions running under cygwin. 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 +(see ). 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. @@ -256,7 +295,7 @@ option on all the Haskell modules that make up your application. Creating a Win32 DLL -––mk-dll +–shared 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: @@ -264,12 +303,12 @@ the DLL by issuing a command of the form: -ghc ––mk-dll -o foo.dll bar.o baz.o wibble.a -lfooble +ghc –shared -o foo.dll bar.o baz.o wibble.a -lfooble -By feeding the ghc compiler driver the option , it +By feeding the ghc compiler driver the 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. @@ -309,12 +348,12 @@ you compile into a DLL must have a common root. By default, the entry points of all the object files will be exported from -the DLL when using . Should you want to constrain +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 +ghc –shared -o .... MyDef.def See Microsoft documentation for details, but a module definition file @@ -333,22 +372,22 @@ EXPORTS -In addition to creating a DLL, the option also +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 +DLL: HScool.dll ==> import lib: libHScool.dll.a 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. +libHSfoo.dll.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 +. By doing this for you, switching from non-static to static linking is simply a question of adding to your command line. @@ -364,121 +403,151 @@ non-static to static linking is simply a question of adding Making DLLs to be called from other languages - -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: - + 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 + ; we'll deal with the DLL-specific issues that + arise below. Here's an example: - - - - -Use foreign export 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: + +-- Adder.hs +{-# LANGUAGE ForeignFunctionInterface #-} module Adder where -adder :: Int -> Int -> IO Int –– 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 - - - - -Compile it up: - - -ghc -c adder.hs -fglasgow-exts - - -This will produce two files, adder.o and adder_stub.o + Add some helper code that starts up and shuts down the Haskell RTS: - - - - -compile up a DllMain() that starts up the Haskell -RTS-––a possible implementation is: - -#include <windows.h> +// StartEnd.c #include <Rts.h> -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 - ) +extern void __stginit_Adder(void); + +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; -} - + int argc = 1; + char* argv[] = {"ghcDll", NULL}; // argv must end with NULL -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). + // Initialize Haskell runtime + char** args = argv; + hs_init(&argc, &args); -Compile this up: + // Tell Haskell about all root modules + hs_add_root(__stginit_Adder); +} +void HsEnd() +{ + hs_exit(); +} + + + 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 everything up: + -ghc -c dllMain.c +ghc -c Adder.hs +ghc -c StartEnd.c +ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o + + Now the file Adder.dll can be used from other + programming languages. Before calling any functions in Adder it is necessary + to call HsStart, and at the very end call + HsEnd. - - - -Construct the DLL: - - -ghc ––mk-dll -o adder.dll adder.o adder_stub.o dllMain.o - - + Warning: It may appear tempting to use + DllMain to call + hs_init/hs_exit, but this won't work + (particularly if you compile with -threaded). There are + severe restrictions on which actions can be performed during + DllMain, and hs_init violates these + restrictions, which can lead to your dll freezing during startup (see + bug + #3605). - - - -Start using adder from VBA-––here's how I would -Declare it: + +Using from VBA + + An example of using Adder.dll from VBA is: + -Private Declare Function adder Lib "adder.dll" Alias "adder@8" +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. +Private Declare Sub HsStart Lib "Adder.dll" () +Private Declare Sub HsEnd Lib "Adder.dll" () + +Private Sub Document_Close() +HsEnd +End Sub + +Private Sub Document_Open() +HsStart +End Sub + +Public Sub Test() +MsgBox "12 + 5 = " & Adder(12, 5) +End Sub + + + This example uses the + Document_Open/Close functions of + Microsoft Word, but provided HsStart is called before the + first function, and HsEnd after the last, then it will + work fine. + + + +Using from C++ -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. + An example of using Adder.dll from C++ is: - + +// Tester.cpp +#include "HsFFI.h" +#include "Adder_stub.h" +#include <stdio.h> + +extern "C" { + void HsStart(); + void HsEnd(); +} - +int main() +{ + HsStart(); + // can now safely call functions from the DLL + printf("12 + 5 = %i\n", adder(12,5)) ; + HsEnd(); + return 0; +} + + + This can be compiled and run with: + + +$ ghc -o tester Tester.cpp Adder.dll.a +$ tester +12 + 5 = 17 + + + @@ -487,7 +556,6 @@ the Haskell source and build the DLL.