Trying to build a Win DLL with Haskell functions, I recognized some
strange things, which look to me like a bug in GHC's garbage collection.
Here's what I did:
1) First Trial:
* Define a module "Foo" (foo.hs):
module Foo where
foreign export stdcall foo :: Int -> IO Int
foo :: Int -> IO Int
foo n = return (length (f n))
f :: Int -> [Int]
f 0 = []
f n = n:(f (n-1))
* Write a def-File (foo.def):
EXPORTS
foo@4
* Define the DllMain function in C (dllMain.c):
#include <windows.h>
#include <Rts.h>
static char* args[] = { "ghcDll" };
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,NULL);
return TRUE;
}
return TRUE;
}
* Compile it up:
ghc -c -static foo.hs -fglasgow-exts
ghc -c -static dllMain.c
ghc -static --mk-dll -optdll--def=foo.def -o foo.dll *.o -lHSrts
* Call "foo" from outside 3 times with the argument 2500:
The first two times the execution succeeds; but the third call ends with
an access violation error ("Zugriffsverletzung bei Adresse 69B89B99.
Lesen von Adresse FFFFFFFF.")
2) Second Trial:
* Write an addional caller-function in C (foo_caller.c), that
start/shuts down the RTS every time calling "foo".
#include "foo_stub.h"
#include "RtsAPI.h"
static char* args[] = { "ghcDll" };
StgInt __stdcall call_foo(StgInt a0)
{
StgInt res;
startupHaskell(1, args,NULL);
res = foo(a0);
shutdownHaskell();
return res;
}
* Adjust the def file:
EXPORTS
foo@4
call_foo@4
* Compile it up:
ghc -c -static foo_caller.c
ghc -static --mk-dll -optdll--def=foo.def -o foo.dll *.o -lHSrts
* Call "call_foo" from outside with the argument 2500:
Now everything seems to be okay, the call can be repeated again and
again without any error.
I use GHC 4.08.1 with cygwin 1.1. - I recognized this kind of error also
when compiling with GHC4.05.
What to do about this?
Christian
foo.hs
foo_caller.c
foo.def
dllMain.c