4

I have a mixed C/C++ library.

On the outside it provides a C interface using extern C. Internally there are templates and classes. Creating the library with "ar" posed no problems. The file is called libo-client.a.

However, when linking the .a file using gcc (not g++) I get lots of errors that look like this:

libo-client.a(mysocket.o):(.rodata._ZTV7mStream[vtable for mStream]+0x10): undefined reference to `__cxa_pure_virtual'
...
mysocket.cpp:(.text+0x15ad): undefined reference to `operator new[](unsigned long)'
mysocket.cpp:(.text+0x15c1): undefined reference to `operator delete(void*)'
mysocket.cpp:(.text+0x167a): undefined reference to `__cxa_allocate_exception'
mysocket.cpp:(.text+0x16a6): undefined reference to `__cxa_throw'
...

My compile/link line looks like this:

gcc $(CFLAGS) $(INCLUDES) test2.c libo-client.a -o test2 

Where test2 is my test harness.

This problem does not occur when I'm using g++. However, I'm going to interface this library into C project which is compiled with gcc. How do I get around this? What's the cause of it?

EDIT:

Even though I'm not using the standard C++ library it's obviously needing some things like operator new/delete etc. and there are exceptions internally.

I'm linking this thing against the Xen hypervisor so I'm not sure what options i have but to totally rewrite this thing or perhaps try compiling Xen with G++ instead?

hookenz
  • 36,432
  • 45
  • 177
  • 286

5 Answers5

11

The simplest way around your problem it is to link with g++; this gets the correct libraries in place.

The problem is that C++ has a lot of requirements that C does not, and does more work before calling main() to ensure that things are properly initialized.

If you insist on linking with the C compiler, at the very least you'd have to include the C++ support library in with your link command.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • +1 - including a C++ library in a C project will take more than just throwing the object files at it. – Carl Norum Sep 13 '11 at 05:50
  • Switching to g++ fixed it for me too, but is there a more portable way? How would I write a Makefile for a non-Linux system? – Edward Falk Mar 18 '13 at 20:48
  • @EdwardFalk: More portable than linking a (partially) C++ program with a C++ compiler? No; that will be the most portable way to do it. The alternative is working out how the C++ compiler invokes the linker to get the C++ stuff done, and then work out how to twist the C compiler into invoking the linker in the same way that the C++ compiler does automatically for you. Be my guest if you want to try, but it will be radically harder to do, and vastly less portable. – Jonathan Leffler Mar 18 '13 at 22:06
  • What if the compiler isn't named "g++". Gnu isn't the only compiler out there. Is there a ${CC++} macro in make, equivalent to ${CC}? – Edward Falk Mar 19 '13 at 03:54
  • 2
    It's usually denoted by the macro `${CXX}`. Where your C compiler is `gcc`, the C++ compiler is usually `g++`. Where you're using different compilers, you still link with the C++ compiler that was used to build the C++ object modules. – Jonathan Leffler Mar 19 '13 at 03:57
  • Perfect; that's what I was looking for. – Edward Falk Mar 19 '13 at 20:04
2

Your C++ library is still a C++ library internally, which means that it contains external references to various housekeeping functions from C++ standard library. In order to resolve these links you'll have to link your final executable for C++ standard library. gcc does not do it for you automatically. Either explicitly supply the C++ standard library to gcc, or use g++ compiler instead.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

An archive is still just a bunch of object files (.o), so when linking them into an executable or shared library, you still need to link with g++ to resolve symbols to the C++ runtime (like the once you see in your error messages).

For your C functions to have C-linkage, it should be enough to wrap them in extern "C" blocks. Things might get more complicated on, e.g. Windows, with it's myriads of linkage macros (STDCALL, WINAPI, etc.) that expand to other stuff (some compiler specific) like __stdcall, __declspec(export), etc.

Christian.K
  • 47,778
  • 10
  • 99
  • 143
1

The errors which you see seem to appear due to missing linkage to Standard C++ library which has the symbol definition for operator new, operator delete etc. Try linking stdc++ say gcc $(CFLAGS) $(INCLUDES) test2.c libo-client.a -o test2 -lstdc++. Better option is as suggested by Jonathan Leffler to use g++ instead of gcc

another.anon.coward
  • 11,087
  • 1
  • 32
  • 38
0

Writing stuff in C++ that can be used from C without any of the extras C++ requires is very hard. Probably even compiler dependent. Your library requires the C++ runtime, and to initialize the C++ runtime presumaby requires special support before caling main() in your program. Your chimaera in still a C++ program when you link in C files, even if it is main() and everything else outside your library.

vonbrand
  • 11,412
  • 8
  • 32
  • 52