This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: Help : Linking C and C++ code


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]