
Hello everyone, we have tried long and hard to call Haskell functions from C++ using the FFI mechanism but without success. Our problem is as follows: We tried the C case first. Taking the example code from Chapter 8.2 of the GHC User Guide, we created files Foo.hs and main.c and then did $ ghc -fffi -c Foo.hs /tmp/ghc28407.hc: In function `__stginit_Foo_': /tmp/ghc28407.hc:278: warning: implicit declaration of function `getStablePtr' $ ghc -fffi Foo. Foo.hi Foo.hs Foo.o $ mv main.cpp main.c $ ghc -fffi Foo.o Foo_stub.o main.c $ ./a.out 2500 2500 2500 2500 2500 which worked fine. But when we simply rename main.c -> main.cpp, then $ ghc -fffi Foo.o Foo_stub.o main.cpp main.o(.text+0x22): In function `main': main.cpp: undefined reference to `__stginit_Foo()' main.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status We tried many different options to ghc and also using g++ directly, all to no avail. It would be really great if someone could shed some light on this. For convenience, we have attached Foo.hs and main.cpp. Thanks, Felix

we have tried long and hard to call Haskell functions from C++ using the FFI mechanism but without success.
Don't forget to say which platform you're on - the solution might be slightly platform-dependent.
$ ghc -fffi Foo.o Foo_stub.o main.cpp main.o(.text+0x22): In function `main': main.cpp: undefined reference to `__stginit_Foo()'
#ifdef __GLASGOW_HASKELL__ extern void __stginit_Foo ( void ); #endif
This should be... extern "C" void __stginit_Foo ( void );
main.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
On Mac OS X, all you need to do is add -lstdc++ to your ghc command line; it may or may not be that easy on other platforms. Cheers, Wolfgang

On 9/13/05, Felix Breuer
$ ghc -fffi Foo.o Foo_stub.o main.cpp main.o(.text+0x22): In function `main': main.cpp: undefined reference to `__stginit_Foo()' main.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
In main.cpp, you need to define __stginit_Foo(void) like this: extern "C" void __stginit_Foo(void); Specifying the "C" linkage with prevent the compiler from looking for a name-mangled version of the function. To fix the second problem, you need to shut off exception handling (specifying the -fno-exceptions option ought to do this. I don't know how to pass compiler option via ghc, though. -- Rich AIM : rnezzy ICQ : 174908475

On Tue, 2005-09-13 at 15:20 +0000, Felix Breuer wrote:
we have tried long and hard to call Haskell functions from C++ using the FFI mechanism but without success.
$ ghc -fffi Foo.o Foo_stub.o main.cpp main.o(.text+0x22): In function `main': main.cpp: undefined reference to `__stginit_Foo()' main.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
Unless Haskell C header files do this (which they should!) you will have to do it yourself for each #include of a header file: extern "C" { #include <some C-only header file> } These header files provided by GHC should be fixed to use the standard artifice: #ifdef __cplusplus extern "C" { #endif rest of the file here ... #ifdef __cplusplus } #endif All C header files should be constructed this way. GNU headers use the macros __BEGIN_DECLS __END_DECLS The problem you are having is simple: C++ supports overloading, so a function called void fred(); in C is named 'fred' or '_fred' by the linker .. and that's that. In C++, you can have this fred and also void fred(int); so these functions have to have different names. They're called mangled or decorated names and are compiler dependent. extern "C" disables C++ name mangling by forcing everything to have the same linkage as the companion C compiler. [There are still some incompatibilities however .. hopefully you won't run into any of them] There is one more problem: you MUST NOT run gcc on files ending in *.cpp. You are REQUIRED to run g++. So you will have to somehow tell ghc to use g++ and NOT gcc. in particular C++ programs require different startup code to C, to initialise exception handling, etc etc. So the whole program MUST be linked by g++, not gcc, and the main() must be compiled with g++ not gcc. Note sure about GHC, but there is only one correct mainline: #ifdef __cplusplus extern "C" #endif int sub(int, char**); int main(int argc, char **argc) { return sub(argc,argv); } This should be the whole mainline .. because this is the only part of the system that must be compiled either as C++ or as C, the rest (called 'sub' above) can be compiled as C. This lets the client choose either C or C++ without burdening the vendor with having to compiled the real code using both. -- John Skaller <skaller at users dot sourceforge dot net>

Hello everyone,
the examples are working now! John, Wolfgang and Rich, thank you for your help!
On Wed, 14 Sep 2005 02:07:52 +1000
skaller
On Tue, 2005-09-13 at 15:20 +0000, Felix Breuer wrote:
main.o(.text+0x22): In function `main': main.cpp: undefined reference to `__stginit_Foo()'
This was solved by extern "C" void __stginit_Foo(void);
main.o(.eh_frame+0x11): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
and this by adding -lstdc++ to the ghc command line options. My platform is Linux 2.6.11 running GCC 3-4-4.. I will now try to apply this to my application. I will see if I run into trouble when I actually use C++ code (and not just rename a C source file).
There is one more problem: you MUST NOT run gcc on files ending in *.cpp. You are REQUIRED to run g++. So you will have to somehow tell ghc to use g++ and NOT gcc. in particular C++ programs require different startup code to C, to initialise exception handling, etc etc. So the whole program MUST be linked by g++, not gcc, and the main() must be compiled with g++ not gcc.
Is it possible to have ghc compile _and_ _link_ all the Haskell code, and then using g++ to compile the C++ code and link everything together? I tried using ghc to only compile the .hs files and have g++ do all the linking but I only got a bunch of undefined references due to the GHC libs not being linked into the executable. I always relied on ghc --make to figure out the dependencies here, and now I don't know which files to link against... Thanks again, Felix
participants (4)
-
Felix Breuer
-
Rich Neswold
-
skaller
-
Wolfgang Thaller