
ac> New to Haskell, new to GHC. My initial intention in picking up
ac> Haskell is to be able to write some functions in Haskell and
then
ac> compile them into .dlls for Win32 that I can call from programs
ac> written in other languages. So before I get too deeply
invested I
ac> want to make sure that is possible.
It's certainly possible. I do it here all the time on a commercial
project. I even volunteered a few months ago to write some better
documentation, but I sadly have not had the time to do it.
As Sigbjorn says, adding -package base when linking the DLL with ghc
will
silence those errors from the linker.
The warning given when compiling the C code in dllMain.c comes from the
declaration of __stginit_Adder as
EXTFUN(__stginit_Adder)
Which is not really the type that startupHaskell expects. Declare it
instead as
extern void __stginit_Adder(void);
and the warning will be silenced.
The much bigger gotcha is that the code in dllMain.c from Sect 11 of
the
user's guide will probably not work, because Windows forbids certain
things
from happening in dllMain (basically, anything that could possibly
cause one
to reattach to the DLL). That includes creating new threads, and that
includes creating timers, and startupHaskell tries to do that. I don't
remember at the moment if it is a problem when the GHC runtime is in a
separate DLL, but it is certainly a problem when linking the GHC
runtime
into the same DLL.
My typical solution is to provide entry points to explicitly startup
and
shutdown the Haskell runtime, outside of a call to dllMain. Here is an
example, calling Adder from Java:
1. Write some Haskell code to implement the add function in the DLL.
Note
that Java will expect a mangled name, which we supply manually:
==== Adder.hs
module Adder (add) where
import Foreign (Ptr, Int32)
data JNIEnv
data JClass
foreign export stdcall "Java_Adder_add"
add :: Ptr JNIEnv -> Ptr JClass -> Int32 -> Int32 -> IO Int32
add :: Ptr JNIEnv -> Ptr JClass -> Int32 -> Int32 -> IO Int32
add _ _ m n = return (m + n)
====================
2. Compile. Don't forget -fglasgow-exts:
ghc -fglasgow-exts -c Adder.hs
3. Write C functions that can be called by Java (mangling the names
again)
and that can be used to startup and shutdown the Haskell runtime.
You
can't do this directly from Java, because the FFI functions don't
have
the mangled names that Java expects, and you can't do it from
Haskell
code for obvious reasons.
==== ccode.c
#include