This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
RE: Help : Linking C and C++ code
- To: "'Ujval Lodha'" <ujval at gdc-tech dot com>
- Subject: RE: Help : Linking C and C++ code
- From: "Rupert Wood" <me at rupey dot net>
- Date: Mon, 12 Nov 2001 07:20:07 -0000
- Cc: <gcc-help at gcc dot gnu dot org>
Ujval Lodha wrote:
> I am trying to link some C code with C++ code. The compiler returns
> with =93undefined reference to <function>=94 for the function
> written in the C++ file.
>
> Please advise on how to call a C++ function from a C program and
> link the two.
In C++, it is valid to have two functions with the same name but
different arguments, e.g.
int foo(int);
char* foo(char*);
and the compiler decides which one to call based on context. However,
the two functions need to be exported with different symbols. Hence C++
'mangles' or 'decorates' the name, adding extra characters to represent
the represent the call parameters (and, where appropriate, namespace,
class, constness, etc.) For example, on my system, the above functions
are exported with names:
int foo(int); => _Z3fooi
char* foo(char*); => _Z3fooPc
Now the problem is that C assumes that symbol names are prefixed with an
underscore (or unchanged - system dependently) and so it can't match the
mangled names. Whilst you could get your C code to call 'Z3fooi'
instead, this probably isn't safe; firstly, the mangled form is compiler
specific and secondly it might not be safe to assume that the C++ code
has the same ABI (Application Binary Interface?) as the C code. Hence
you should export the C++ function as 'extern "C"'; e.g. either of:
extern "C" int foo(int);
int foo(int a) { return a + 1; }
or
extern "C" int foo(int a) { return a + 1; }
However, this will only work for plain functions; if you need C++
mangled names (e.g. a class static function) then you should create an
extern "C" wrapper function, e.g.:
class bar {
public:
static int foo(int);
};
int bar::foo(int a) { return a + 1; }
extern "C" int C_foo(int a) { return bar::foo(a); }
which you can call from your C code as normal.
If you need a combined C/C++ header, you can wrap the 'extern "C"' in
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
int foo(int);
#ifdef __cplusplus
}
#endif
Good luck,
Rup.