简体   繁体   中英

Why can't I link a mixed C/C++ static library that has a C interface using gcc?

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?

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.

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.

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, eg Windows, with it's myriads of linkage macros (STDCALL, WINAPI, etc.) that expand to other stuff (some compiler specific) like __stdcall, __declspec(export), etc.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM