diff options
Diffstat (limited to 'docs/users_guide/win32-dlls.xml')
-rw-r--r-- | docs/users_guide/win32-dlls.xml | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/docs/users_guide/win32-dlls.xml b/docs/users_guide/win32-dlls.xml deleted file mode 100644 index 1168871c10..0000000000 --- a/docs/users_guide/win32-dlls.xml +++ /dev/null @@ -1,575 +0,0 @@ -<?xml version="1.0" encoding="iso-8859-1"?> -<chapter id="win32"> -<title>Running GHC on Win32 systems</title> - -<sect1 id="ghc-windows"> -<title> -Starting GHC on Windows platforms</title> - -<para> -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 <command>ghci</command>. -</para> -<para> -Be aware of that <command>ghc</command> and <command>ghci</command> do -require filenames containing spaces to be escaped using quotes: -<programlisting> - c:\ghc\bin\ghci "c:\\Program Files\\Haskell\\Project.hs" -</programlisting> -If the quotes are left off in the above command, <command>ghci</command> will -interpret the filename as two, "c:\\Program" and "Files\\Haskell\\Project.hs". -</para> - -<!-- not clear whether there are current editions of Win32 OSes that - doesn't do this by default. - -<para> Solution: don't use "Open With...", avoid spaces in file names, -or fiddle with the appropriate registry setting: -<programlisting> - HKEY_CLASSES_ROOT\Unknown\shell\openas\command -</programlisting> -Notice how the "%1" argument is quoted (or not). -</para> -<para> This problem doesn't occur when double-clicking. -</para> ---> - -</sect1> - -<sect1 id="ghci-windows"> -<title>Running GHCi on Windows</title> - - <para>We recommend running GHCi in a standard Windows console: - select the <literal>GHCi</literal> option from the start menu item - added by the GHC installer, or use - <literal>Start->Run->cmd</literal> to get a Windows console and - invoke <literal>ghci</literal> from there (as long as it's in your - <literal>PATH</literal>).</para> - - <para>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 <literal>ghcii.sh</literal> 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 <literal>ghcii.sh</literal> 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.</para> - - <para>There's an exception: you can use a Cygwin shell if the - <literal>CYGWIN</literal> environment variable does - <emphasis>not</emphasis> contain <literal>tty</literal>. In this - mode, the Cygwin shell behaves like a Windows console shell and - console events are propagated to child processes. Note that the - <literal>CYGWIN</literal> environment variable must be set - <emphasis>before</emphasis> starting the Cygwin shell; changing it - afterwards has no effect on the shell.</para> - - <para>This problem doesn't just affect GHCi, it affects any - GHC-compiled program that wants to catch console events. See the - <ulink - url="&libraryBaseLocation;/GHC-ConsoleHandler.html">GHC.ConsoleHandler</ulink> - module.</para> -</sect1> - -<sect1 id="terminal-interaction"> -<title> -Interacting with the terminal</title> - -<para>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 -<literal>-optl-mwindows</literal> in the link step. -</para> - -<para> <emphasis>Warning:</emphasis> 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: -<screen> - Fail: <stdout>: hPutChar: failed (Bad file descriptor) -</screen> - However using Debug.Trace.trace is alright because it uses - Windows debugging output support rather than stderr.</para> - -<para>For some reason, Mingw ships with the <literal>readline</literal> library, -but not with the <literal>readline</literal> headers. As a result, GHC (like Hugs) does not -use <literal>readline</literal> for interactive input on Windows. -You can get a close simulation by using an emacs shell buffer! -</para> - -</sect1> - -<sect1 id="library-differences"> -<title> -Differences in library behaviour </title> - -<para> -Some of the standard Haskell libraries behave slightly differently on Windows. - -<itemizedlist> -<listitem> <para> -On Windows, the '<literal>^Z</literal>' 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 <literal>IOExts.openFileEx</literal> to open a file in binary -(untranslated) mode or change an already opened file handle into -binary mode using <literal>IOExts.hSetBinaryMode</literal>. The -<literal>IOExts</literal> module is part of the -<literal>lang</literal> package. -</para> -</listitem> -</itemizedlist> -</para> -</sect1> - -<sect1 id="ghci-cygwin"> -<title> -Using GHC (and other GHC-compiled executables) with cygwin</title> - -<sect2> -<title>Background</title> <para>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 -<filename>/</filename> is <filename>C:\cygwin\</filename>). 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 <filename>/bin</filename> and <filename>/usr/include</filename> without -ever explicitly bothering with their actual location on the windows -system (probably <filename>C:\cygwin\bin</filename> and <filename>C:\cygwin\usr\include</filename>). -</para> -</sect2> - -<sect2><title>The problem</title> -<para>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 <filename>/home/joe/Main.hs</filename> or <filename>/bin/bash</filename> -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. -</para> -</sect2> - -<sect2><title>Things to do</title> -<itemizedlist> -<listitem> -<para> 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. -</para></listitem> - -<listitem> -<para> If you have to use absolute paths (beware of the innocent-looking - <literal>ROOT=`pwd`</literal> in makefile hierarchies or configure scripts), cygwin provides - a tool called <command>cygpath</command> 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 - <command>cygpath</command> just before they are passed to GHC and friends. -</para></listitem> - -<listitem> -<para> If you don't have <command>cygpath</command>, 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: -<programlisting> - $ echo "Directory.getCurrentDirectory >>= putStrLn . init . tail . show " | ghci -</programlisting> -</para></listitem> -</itemizedlist> -</sect2> -</sect1> - - -<sect1 id="win32-dlls"> -<title>Building and using Win32 DLLs -</title> - -<para> -<indexterm><primary>Dynamic link libraries, Win32</primary></indexterm> -<indexterm><primary>DLLs, Win32</primary></indexterm> -On Win32 platforms, the compiler is capable of both producing and using -dynamic link libraries (DLLs) containing ghc-compiled code. This -section shows you how to make use of this facility. -</para> - -<para> -There are two distinct ways in which DLLs can be used: -<itemizedlist> - <listitem> - <para> - You can turn each Haskell package into a DLL, so that multiple - Haskell executables using the same packages can share the DLL files. - (As opposed to linking the libraries statically, which in effect - creates a new copy of the RTS and all libraries for each executable - produced.) - </para> - <para> - That is the same as the dynamic linking on other platforms, and it - is described in <xref linkend="using-shared-libs"/>. - </para> - </listitem> - <listitem> - <para> - You can package up a complete Haskell program as a DLL, to be called - by some external (usually non-Haskell) program. This is usually used - to implement plugins and the like, and is described below. - </para> - </listitem> -</itemizedlist> -</para> - -<!-- -<para> -Until recently, <command>strip</command> 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). -</para> - - -<sect2 id="win32-dlls-link"> -<title>Linking with DLLs</title> - -<para> -The default on Win32 platforms is to link applications in such a way -that the executables will use the Prelude and system libraries DLLs, -rather than contain (large chunks of) them. This is transparent at the -command-line, so -</para> - -<para> -<screen> -sh$ cat main.hs -module Main where -main = putStrLn "hello, world!" -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 4608 May 3 17:11 main.exe* -sh$ ./main -hello, world! -sh$ -</screen> -</para> - -<para> -will give you a binary as before, but the <filename>main.exe</filename> -generated will use the Prelude and RTS DLLs instead of linking them in -statically. -</para> - -<para> -4K for a <literal>"hello, world"</literal> application—not bad, huh? :-) -</para> - -</sect2> - -<sect2 id="win32-dlls-linking-static"> -<title>Not linking with DLLs -<indexterm><primary>-static option (Win32)</primary></indexterm></title> - -<para> -If you want to build an executable that doesn't depend on any -ghc-compiled DLLs, use the <option>-static</option> option to link in -the code statically. -</para> - -<para> -Notice that you cannot mix code that has been compiled with -<option>-static</option> and not, so you have to use the <option>-static</option> -option on all the Haskell modules that make up your application. -</para> - -</sect2> ---> - -<sect2 id="win32-dlls-create"> -<title>Creating a DLL</title> - -<para> -<indexterm><primary>Creating a Win32 DLL</primary></indexterm> -<indexterm><primary>-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: -</para> - -<para> -<screen> -ghc -shared -o foo.dll bar.o baz.o wibble.a -lfooble -</screen> -</para> - -<para> -By feeding the ghc compiler driver the option <option>-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. -</para> - -<!-- -<para> -To create a `static' DLL, i.e. one that does not depend on the GHC DLLs, -use the <option>-static</option> when compiling up your Haskell code and -building the DLL. -</para> ---> - -<para> -A couple of things to notice: -</para> - -<para> - -<itemizedlist> -<!-- -<listitem> -<para> -Since DLLs correspond to packages (see <xref linkend="packages"/>) you need -to use <option>-package-name dll-name</option> 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 <function>startupHaskell</function> needs to be able to call its -initialisation function, and only takes one such argument (see <xref -linkend="win32-dlls-foreign"/>). Hence the modules -you compile into a DLL must have a common root. -</para> -</listitem> ---> - -<listitem> -<para> -By default, the entry points of all the object files will be exported from -the DLL when using <option>-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 -shared -o .... MyDef.def -</screen> - -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: - -<programlisting> -EXPORTS - DllCanUnloadNow = DllCanUnloadNow@0 - DllGetClassObject = DllGetClassObject@12 - DllRegisterServer = DllRegisterServer@0 - DllUnregisterServer = DllUnregisterServer@0 -</programlisting> -</para> -</listitem> - -<listitem> -<para> -In addition to creating a DLL, the <option>-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 ==> 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.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.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. - -</para> -</listitem> -</itemizedlist> -</para> - -</sect2> - - -<sect2 id="win32-dlls-foreign"> -<title>Making DLLs to be called from other languages</title> - -<para> - 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 - <xref linkend="ffi-library" />; we'll deal with the DLL-specific issues that - arise below. Here's an example: -</para> -<para> - Use foreign export declarations to export the Haskell functions you want to - call from the outside. For example: -</para> -<programlisting> --- Adder.hs -{-# LANGUAGE ForeignFunctionInterface #-} -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 -</programlisting> -<para> - Add some helper code that starts up and shuts down the Haskell RTS: -</para> -<programlisting> -// StartEnd.c -#include <Rts.h> - -void HsStart() -{ - int argc = 1; - char* argv[] = {"ghcDll", NULL}; // argv must end with NULL - - // Initialize Haskell runtime - char** args = argv; - hs_init(&argc, &args); -} - -void HsEnd() -{ - hs_exit(); -} -</programlisting> -<para> - Here, <literal>Adder</literal> 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: -</para> -<screen> -ghc -c Adder.hs -ghc -c StartEnd.c -ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o -</screen> -<para> - Now the file <filename>Adder.dll</filename> can be used from other - programming languages. Before calling any functions in Adder it is necessary - to call <literal>HsStart</literal>, and at the very end call - <literal>HsEnd</literal>. -</para> -<para> - <emphasis>Warning:</emphasis> It may appear tempting to use - <literal>DllMain</literal> to call - <literal>hs_init</literal>/<literal>hs_exit</literal>, but this won't work - (particularly if you compile with <literal>-threaded</literal>). There are - severe restrictions on which actions can be performed during - <literal>DllMain</literal>, and <literal>hs_init</literal> violates these - restrictions, which can lead to your dll freezing during startup (see - <ulink url="http://ghc.haskell.org/trac/ghc/ticket/3605">bug - #3605</ulink>). -</para> - -<sect3 id="win32-dlls-vba"> -<title>Using from VBA</title> - -<para> - An example of using <filename>Adder.dll</filename> from VBA is: -</para> -<programlisting> -Private Declare Function Adder Lib "Adder.dll" Alias "adder@8" _ - (ByVal x As Long, ByVal y As Long) As Long - -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 -</programlisting> -<para> - This example uses the - <literal>Document_Open</literal>/<literal>Close</literal> functions of - Microsoft Word, but provided <literal>HsStart</literal> is called before the - first function, and <literal>HsEnd</literal> after the last, then it will - work fine. -</para> -</sect3> - -<sect3 id="win32-dlls-c++"> -<title>Using from C++</title> - -<para> - An example of using <filename>Adder.dll</filename> from C++ is: -</para> - -<programlisting> -// 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; -} -</programlisting> -<para> - This can be compiled and run with: -</para> -<screen> -$ ghc -o tester Tester.cpp Adder.dll.a -$ tester -12 + 5 = 17 -</screen> - -</sect3> - -</sect2> - -</sect1> -</chapter> - -<!-- Emacs stuff: - ;;; Local Variables: *** - ;;; sgml-parent-document: ("users_guide.xml" "book" "chapter") *** - ;;; ispell-local-dictionary: "british" *** - ;;; End: *** - --> |