X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=docs%2Fusers_guide%2Fwin32-dlls.xml;fp=docs%2Fusers_guide%2Fwin32-dlls.xml;h=959f7ce1b65f67a1c9690343c1e5c8d45e95682f;hb=0065d5ab628975892cea1ec7303f968c3338cbe1;hp=0000000000000000000000000000000000000000;hpb=28a464a75e14cece5db40f2765a29348273ff2d2;p=ghc-hetmet.git diff --git a/docs/users_guide/win32-dlls.xml b/docs/users_guide/win32-dlls.xml new file mode 100644 index 0000000..959f7ce --- /dev/null +++ b/docs/users_guide/win32-dlls.xml @@ -0,0 +1,493 @@ + + +Running GHC on Win32 systems + + + +Starting GHC on Win32 platforms + + +The installer that installs GHC on Win32 also sets up the file-suffix associations +for ".hs" and ".lhs" files so that double-clicking them starts ghci. + + +Be aware of that ghc and ghci do +require filenames containing spaces to be escaped using quotes: + + c:\ghc\bin\ghci "c:\\Program Files\\Haskell\\Project.hs" + +If the quotes are left off in the above command, ghci will +interpret the filename as two, "c:\\Program" and "Files\\Haskell\\Project.hs". + + + + + + + + +Interacting with the terminal + +By default GHC builds applications that open a console window when they start. +If you want to build a GUI-only application, with no console window, use the flag +-optl-mwindows in the link step. + + + Warning: Windows GUI-only programs have no + stdin, stdout or stderr so using the ordinary Haskell + input/output functions will cause your program to fail with an + IO exception, such as: + + Fail: <stdout>: hPutChar: failed (Bad file descriptor) + + However using Debug.Trace.trace is alright because it uses + Windows debugging output support rather than stderr. + +For some reason, Mingw ships with the readline library, +but not with the readline headers. As a result, GHC (like Hugs) does not +use readline for interactive input on Windows. +You can get a close simulation by using an emacs shell buffer! + + + + + + +Differences in library behaviour + + +Some of the standard Haskell libraries behave slightly differently on Windows. + + + +On Windows, the '^Z' character is interpreted as an +end-of-file character, so if you read a file containing this character +the file will appear to end just before it. To avoid this, +use IOExts.openFileEx to open a file in binary +(untranslated) mode or change an already opened file handle into +binary mode using IOExts.hSetBinaryMode. The +IOExts module is part of the +lang package. + + + + + + + + +Using GHC (and other GHC-compiled executables) with cygwin + + +Background The cygwin tools aim to provide a +unix-style API on top of the windows libraries, to facilitate ports of +unix software to windows. To this end, they introduce a unix-style +directory hierarchy under some root directory (typically +/ is C:\cygwin\). Moreover, +everything built against the cygwin API (including the cygwin tools +and programs compiled with cygwin's ghc) will see / as the root of +their file system, happily pretending to work in a typical unix +environment, and finding things like /bin and /usr/include without +ever explicitly bothering with their actual location on the windows +system (probably C:\cygwin\bin and C:\cygwin\usr\include). + + + +The problem +GHC, by default, no longer depends on cygwin, but is a native +windows program. It is built using mingw, and it uses mingw's ghc +while compiling your Haskell sources (even if you call it from +cygwin's bash), but what matters here is that - just like any other +normal windows program - neither GHC nor the executables it produces +are aware of cygwin's pretended unix hierarchy. GHC will happily +accept either '/' or '\' as path separators, but it won't know where +to find /home/joe/Main.hs or /bin/bash +or the like. This causes all +kinds of fun when GHC is used from within cygwin's bash, or in +make-sessions running under cygwin. + + + +Things to do + + + Don't use absolute paths in make, configure & co if there is any chance + that those might be passed to GHC (or to GHC-compiled programs). Relative + paths are fine because cygwin tools are happy with them and GHC accepts + '/' as path-separator. And relative paths don't depend on where cygwin's + root directory is located, or on which partition or network drive your source + tree happens to reside, as long as you 'cd' there first. + + + + If you have to use absolute paths (beware of the innocent-looking + ROOT=`pwd` in makefile hierarchies or configure scripts), cygwin provides + a tool called cygpath that can convert cygwin's unix-style paths to their + actual windows-style counterparts. Many cygwin tools actually accept + absolute windows-style paths (remember, though, that you either need + to escape '\' or convert '\' to '/'), so you should be fine just using those + everywhere. If you need to use tools that do some kind of path-mangling + that depends on unix-style paths (one fun example is trying to interpret ':' + as a separator in path lists..), you can still try to convert paths using + cygpath just before they are passed to GHC and friends. + + + + If you don't have cygpath, you probably don't have cygwin and hence + no problems with it... unless you want to write one build process for several + platforms. Again, relative paths are your friend, but if you have to use + absolute paths, and don't want to use different tools on different platforms, + you can simply write a short Haskell program to print the current directory + (thanks to George Russell for this idea): compiled with GHC, this will give + you the view of the file system that GHC depends on (which will differ + depending on whether GHC is compiled with cygwin's gcc or mingw's + gcc or on a real unix system..) - that little program can also deal with + escaping '\' in paths. Apart from the banner and the startup time, + something like this would also do: + + $ echo "Directory.getCurrentDirectory >>= putStrLn . init . tail . show " | ghci + + + + + + + + +Building and using Win32 DLLs + + + +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 +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. + + + + +Creating a DLL + + +Creating a Win32 DLL +––mk-dll +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: + + + + +ghc ––mk-dll -o foo.dll bar.o baz.o wibble.a -lfooble + + + + +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. + + + + + +A couple of things to notice: + + + + + + + + + +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 + + + + + + +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 + + +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 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 + +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 + + + + + +compile up a DllMain() that starts up the Haskell +RTS-––a possible implementation is: + + +#include <windows.h> +#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 + ) +{ + 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: + + +ghc -c dllMain.c + + + + + + +Construct the DLL: + + +ghc ––mk-dll -o adder.dll adder.o adder_stub.o dllMain.o + + + + + + + +Start using adder from VBA-––here's how I would +Declare it: + + +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. + + + +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. + + + + + + + + + + + +