Problem exporting Haskell to C via a DLL in GHC 6.6
Simon Marlow
simonmarhaskell at gmail.com
Tue Feb 6 05:01:43 EST 2007
SevenThunders wrote:
> Before I post this as a bug, I thought I'd check to make sure I'm not doing
> something wrong.
> For this test case, on my windows XP machine I create a simple Haskell
> routine that counts the characters in a file,
> create a DLL for that routine and call it from C. The C code gives the
> correct answer (I think) but then
> proceeds to hang and never terminate.
I wonder if you're hitting this bug:
http://hackage.haskell.org/trac/ghc/ticket/926
if so, it's slightly worrying that the same thing happens if you just link your
program directly to the DLL, rather than loading it explicitly.
Cheers,
Simon
> If the readFile call is removed from
> this code, and a constant output is assigned to the variable ll, the code
> works fine and terminates correctly. Thus the bug may possibly be some kind
> of interaction with the file IO routine, if it's a bug at all.
>
> First the Haskell code:
>
> baddll.hs:
>
> module Bad
> where
> import Foreign.Ptr
> import Foreign.C.String
> import Foreign.C.Types (CInt, CDouble )
>
> foreign export stdcall badfunc :: CString -> IO (CInt)
> --
> -- | Conversion from Int to CInt
> mkCInt :: Int -> CInt
> mkCInt n = fromIntegral n
>
> badfunc fstr = do
> file <- peekCAString fstr
> sstr <- readFile file
> let ll = length sstr
> return $ mkCInt ll
>
> The C code:
> #include <stdio.h>
> __declspec(dllimport) int __stdcall badfunc(char *outfile) ;
>
>
> int main(int argc, char *argv)
> {
> int ll ;
> ll = badfunc("bad.txt") ;
> printf("ll = %d\n", ll) ;
> return(1) ;
> }
>
> The .bat file used to compile everything. (Assumes ghc and MS VC++ 6.0 is
> in my path)
> baddll.bat:
>
> ghc -O2 -static -c baddll.hs -fglasgow-exts
> ghc -c dllBad.c
> ghc --mk-dll -static -fglasgow-exts -o baddll.dll dllBad.o baddll.o
> baddll_stub.o -L"." -L"." -optdll--def -optdllbaddll.def
> lib /def:baddll.def /MACHINE:X86
> cl baddll.c baddll.lib
>
> The .def file used to create the dll export symbols.
> baddll.def
> LIBRARY baddll.dll
> EXPORTS
> badfunc at 4
> badfunc = badfunc at 4
>
> The boilerplate code to load and unload the Haskell runtime inside the DLL.
> dllBad.c
> #include <windows.h>
> #include <Rts.h>
>
> extern void __stginit_Bad(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_Bad);
> return TRUE;
> }
>
> if (reason == DLL_PROCESS_DETACH) {
> shutdownHaskell();
> return TRUE;
> }
>
> return TRUE;
> }
>
>
> The text file I read in.
> bad.txt:
>
> Greetings Earthlings
>
>
> If I recall correctly, from another piece of test code, this seemed to work
> OK in GHC 6.4. However, I'll have to resurrect my GHC 6.4 installation to
> verify this. If anyone sees an obvious problem with my code I'd love to be
> informed about this.
More information about the Glasgow-haskell-users
mailing list