[Haskell-cafe] Basic FFI with GHC

Ronald Guida ronguida at mindspring.com
Wed Sep 12 15:18:05 EDT 2007


Ronald Guida wrote:
 > How do I create C-libraries that I can load into GHCi?  I am trying to
 > do some basic FFI, and it's not working.

So, after more searching on the internet and some RTFM, I think I
found my answer, and it seems to work, but I don't know if it's the
right answer to generalize from.

1. I can leave "test_foo.lhs" and "foo.cpp" as-is.

2. I need to change "foo.h" to the following:

------------------
// foo.h

#if BUILD_DLL
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif

extern "C"
{
  DECLSPEC __stdcall int foo(int x);
}
------------------

3. I need to create a DEF file and list the functions to be exported
   in a DLL.

------------------
  foo.def
------------------
LIBRARY foo
DESCRIPTION "Foo Library"
EXPORTS
   foo
------------------

 Note: The library name on the first line must match the dll name.
       "LIBRARY foo" corresponds to "foo.dll"

4. The build process is as follows.

 (1) gcc -DBUILD_DLL -c foo.cpp

 (2) gcc -shared -o foo.dll foo.o foo.def \
    -Wl,--enable-stdcall-fixup,--out-implib,libfoo.a

5. At this point, I'll have "foo.dll" and "libfoo.a".  I can load my
   "foo" library, as a DLL, into GHCi with the command:
     $ ghci -lfoo
   In reality, I would use:
     $ ghci test_foo.lhs -lfoo

6. Once I'm satisfied and ready to compile:

    ghc --make test_foo.lhs -L. -lfoo

 Notes:
 (1) "-L." directs GHC to look in the current directory for
     libraries.  GHCi seems to look there by default.

 (2) The resulting "test_foo.exe" will dynamicly load "foo.dll".

7. If I want a staticly linked executable instead:

    ar rcs libfoo_static.a foo.o
    ghc --make test_foo.lhs -L. -lfoo_static

8. Finally, I can put the build steps into a makefile.

------------------
# Makefile for foo

test_foo.exe : test_foo.lhs libfoo.a foo.dll
    ghc --make test_foo.lhs -L. -lfoo

test_foo_static.exe : test_foo.lhs libfoo_static.a
    ghc --make test_foo.lhs -L. -lfoo_static -o test_foo_static.exe

libfoo.a : foo.dll

foo.dll : foo.o foo.def
    gcc -shared -o foo.dll foo.o foo.def \
    -Wl,--enable-stdcall-fixup,--out-implib,libfoo.a

libfoo_static.a : foo.o
    ar rcs libfoo_static.a foo.o

foo.o : foo.cpp foo.h
    gcc -DBUILD_DLL -c foo.cpp

.PHONY: clean
clean:
    rm -f *.[oa]
    rm -f *.dll
    rm -f *.hi
    rm -f *.exe
------------------

-- Ron



More information about the Haskell-Cafe mailing list