
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. Here's the background. I created three files, foo.h, foo.cpp, and test_foo.lhs. (source code below) Note: I am using MinGW/Msys under Windows XP. If I compile foo.cpp and then try to load test_foo into GHCi, I get an error. OTOH, if I compile test_foo with GHC, it works. I just don't understand why it works one way and not the other. What am I doing wrong? -- Ron ------------------------------ Shell commands ------------------------------ $ gcc -c foo.cpp $ ghci test_foo.lhs foo.o ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Loading object (static) foo.o ... done final link ... done [1 of 1] Compiling Main ( test_foo.lhs, interpreted ) During interactive linking, GHCi couldn't find the following symbol: foo This may be due to you not asking GHCi to load extra object files, [snip] $ ghc --make test_foo.lhs foo.o [1 of 1] Compiling Main ( test_foo.lhs, test_foo.o ) Linking test_foo.exe ... $ test_foo.exe Entering main y = 22 Exiting main $ ar rcs libfoo.a foo.o $ ghc --make test_foo.lhs -lfoo $ test_foo.exe Entering main y = 22 Exiting main $ ghci test_foo.lhs -lfoo ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.6.1, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help. Loading package base ... linking ... done. Loading object (dynamic) foo ... failed. Dynamic linker error message was: addDLL: unknown error Whilst trying to load: (dynamic) foo Directories to search are: : user specified .o/.so/.DLL could not be loaded. ------------------------------ Source code ------------------------------ // foo.h extern "C" { __stdcall int foo(int x); } ------------------------------ // foo.cpp #include "foo.h" __stdcall int foo(int x) { return 3 * x + 1; } ------------------------------ test_foo.lhs
{-# OPTIONS_GHC -fglasgow-exts #-} module Main where import Foreign import Foreign.C
foreign import stdcall unsafe "foo" c_Foo :: Word32 -> IO Word32
main = do putStrLn "Entering main" let x = 7::Word32 y <- c_Foo(x) putStrLn $ "y = " ++ show y putStrLn "Exiting main"

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

Hello Ronald, Wednesday, September 12, 2007, 11:18:05 PM, you wrote:
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.
i have added your recipe to http://www.haskell.org/haskellwiki/FFI_cook_book -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

| > 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. | | i have added your recipe to http://www.haskell.org/haskellwiki/FFI_cook_book Thank you Bulat. There's also a GHC page about the FFI here: http://haskell.org/haskellwiki/GHC/Using_the_FFI It seems reasonable to have two: one generic to Haskell and one specific to GHC. - But it would make sense to add a pointer from the generic one to the GHC one - And perhaps some of the material on the GHC page is actually generic, and should be moved? Simon

Hello Simon, Thursday, September 13, 2007, 2:12:18 PM, you wrote:
There's also a GHC page about the FFI here: http://haskell.org/haskellwiki/GHC/Using_the_FFI
this page, despite its name, is only about dealing with Visual C++ via DLLs. it's cookbook-style material, although rather long to be merged with former page
It seems reasonable to have two: one generic to Haskell and one specific to GHC. - But it would make sense to add a pointer from the generic one to the GHC one
done
- And perhaps some of the material on the GHC page is actually generic, and should be moved?
current "ghc material" is step-by-step recipe of implementing one particular application and i think that another description should be written if we want split it into ghc-specific and common parts moreover, i bet that there are not too much non-ghc FFI users, so it will be hard and almost useless to work on such splitting :( -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (3)
-
Bulat Ziganshin
-
Ronald Guida
-
Simon Peyton-Jones