
On 10 March 2011 04:04, Jason Dusek
I'm trying to hew relatively close to Duncan Coutts' blog posting in working through this; so I have different code and a new Makefile:
Starting with your code I've managed to make it work (OS X 10.6, GHC 7). The Makefile is: """ loadfoo: loadfoo.c gcc -arch i386 loadfoo.c -o loadfoo libfoo.dynamic-dynamic.so: Foo.hs fooinit.c ghc -fPIC -c fooinit.c ghc --make -dynamic -fPIC -c Foo.hs ghc -shared -dynamic -o libfoo.dynamic-dynamic.so \ Foo.o Foo_stub.o fooinit.o \ -lHSrts_debug-ghc7.0.1.20101215 test: loadfoo libfoo.dynamic-dynamic.so ./loadfoo libfoo.dynamic-dynamic.so """ (I have to build loadfoo in 32-bit mode because GHC generates 32-bit code on OS X). The fact that we supply the RTS to the GHC link line is important because the shared library would not otherwise link against any particular RTS - in the normal course of things, GHC only decides on the RTS when linking the final executable. I'm linking against the debug RTS there but it should work with the normal one too - I just used the debug version to work out why I got a bus error upon load.. .. and the reason was that your fooinit.c was buggy - that probably account for the crashes you were seeing. The problem is that hs_init takes a *pointer to* argc and argv, not argc and argv directly. You supplied 0 for both of these so GHC died when it tried to dereference them. My new fooinit.c (that works) is as follows: """ #include "HsFFI.h" extern void __stginit_Foo(void); static void Foo_init (void) __attribute__ ((constructor)); void Foo_init (void) { char *arg1 = "fake-main"; char *argv[1] = { arg1 }; char **argv_p = argv; char ***pargv_p = &argv_p; int argc = sizeof(argv) / sizeof(char *); hs_init(&argc, pargv_p); hs_add_root(__stginit_Foo); } """ (Apologies for the extreme ugliness, it's been so long since I wrote C in anger the chain of initializers is the only way I could get this to build without a GCC warning about casts between different pointer types). I tested it with this Foo.hs: """ {-# LANGUAGE ForeignFunctionInterface #-} module Foo where import Foreign.C foreign export ccall foo :: CInt -> CInt foo :: CInt -> CInt foo = (+1) """ And a change to loadfoo.c that actually tries to calls foo: """ printf("**** %s\n", "symbol lookup okay"); + printf("%d\n", foo(1336)); } else { """ (You need "int (*foo)(int) = dlsym(dl, "foo")" as well) The output is 1337 as expected. Cheers, Max