FFI: calling Haskell from C++?

skaller skaller at users.sourceforge.net
Tue Sep 13 12:07:52 EDT 2005


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>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://www.haskell.org//pipermail/glasgow-haskell-users/attachments/20050914/2c736c81/attachment.bin


More information about the Glasgow-haskell-users mailing list