3

I am trying to add some code to a larger C project that requires the use of a C++ library.

The C++ library provides a wrapper using functions marked extern "C" that provide access to the functionality of the library

//Some C++ library
//mywrapper.h
#ifdef __cplusplus
extern "C" {
#endif

void wrapperFunction1( int width );
void wrapperFunction1( int height);
#ifdef __cplusplus
} // extern "C"
#endif

This compiles with g++ without problem.

When making a C program and including mywrapper.h, I continually get linker errors referencing vtable and cxa_pure_virtual:

undefined reference to `vtable for __cxxabiv1::__class_type_info'
undefined reference to `__cxa_pure_virtual'

In testing, these errors go away and allow the program to compile when I add the stdc++ library, but this isn't a option for the larger C project. Is there a way to compile a C program to access a C++ library without these errors and without stdc++? And the deals of the errors are referring to modules that are deep inside of the C++ library and not referenced in mywrapper.h, so why is C program even trying to refer to them?

Michael Curran
  • 131
  • 1
  • 3

5 Answers5

8

A C++ library depends on standard C++ library (libstdc++, -lstdc++ option to linker, defaulted if you run linker via g++). That's a fact. Nothing can be done about it. Get over it.

The wrapper header does not refer to those symbols, but the actual object files in the library do. So they need to be defined and the way to define them is to include the standard C++ library.

Note, that if the wrapped library itself is dynamic, it will know it's dependencies and you won't have to specify linking against libstdc++ dynamically.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • That was my first thought too, but I still get the same errors: ./lib.so: undefined reference to `__cxa_pure_virtual' ./lib.so: undefined reference to `vtable for __cxxabiv1::__si_class_type_info' ./lib.so: undefined reference to `vtable for __cxxabiv1::__class_type_info' – Michael Curran Jan 26 '12 at 15:19
  • @MichaelCurran: Did you link the library with C++ compiler driver (g++)? – Jan Hudec Jan 27 '12 at 07:35
  • I can't, the project tool chain is just gcc. – Michael Curran Jan 27 '12 at 22:31
  • @MichaelCurran: The wrapper library is under your control, no? If you make it dynamic, it will know it's dependencies. Or you should be able to override the compiler flags somehow. You don't need to link with `g++`; adding `-lstdlibc++` to linker command-line is enough. – Jan Hudec Jan 30 '12 at 08:57
3

It is the C++ library you've wrapped that requires stdc++, not your wrapper.

You've wrapped the C++ functions so that they are callable from C but they still use a library internally that depends on the C++ standard library. If you don't provide stdc++, the library you're using is missing part of its implementation. Unless you rewrite the C++ library, there is no way round that.

thehouse
  • 7,957
  • 7
  • 33
  • 32
  • Were that the case, shouldn't I be getting linker errors for all the "std::" stuff in all the library's objects instead of just the vtable stuff? – Michael Curran Jan 26 '12 at 14:21
  • @MichaelCurran: If the C++ library doesn't use any functions or objects from the standard library, those symbols won't show up. It will still need to use the C++ library for basic runtime support. – Dietrich Epp Jan 26 '12 at 14:44
  • The code is littered with std:: calls and those start to show up if I compile without "-lm", only the vtable and cxa_pure_virtual errors require libstdc++ to clear. – Michael Curran Jan 26 '12 at 16:13
  • 1
    It's possible that your C++ standard library implementation implements much of the std:: namespace in header files. Therefore it gets compiled into your program directly. However that parts of it that are compiled seperately still need linking in. – thehouse Jan 27 '12 at 11:33
1

It is perfectly valid not to include libstdc++ with some caveats. Depending on what you do in the C++ code (or in this case the library you're wrapping) it may expect the underlying runtime to provide certain functions:

  • Like you mention, RTTI info
  • __cxa_pure_virtual if you have unimplemented pure virtual functions (for example, in pure abstract classes)
  • Calls to constructors before main() and destructors after it

This happens not only when you don't include libstdc++ library, but also on stripped down custom versions of the library.

For example, Rowley Crossworks for ARM (toolchain for embedded systems) recommends that you write __cxa_pure_virtual error handler yourself.

Ian M. García
  • 721
  • 5
  • 3
1

In general C++ code needs some level of run-time support to deal with specific C++ features. For example, there is a library function dealing with dynamic_cast<>(). Even if you don't use any of the standard C++ library you will need this language support libray. It is typically included in the standard C++ library but specifically for gcc this library is separately available. That is, you may get away with not including libstdc++ but you won't get away including this library. At the moment I can't find out how it is called though. I think it is -lcxxabi but I'm not sure.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

Okay, I've done some more research and I stumbled over the answer, I had two problems, first was the error messages:

./lib.so: undefined reference to vtable for __cxxabiv1::__si_class_type_info' 
./lib.so: undefined reference to `vtable for __cxxabiv1::__class_type_info'

These are related to C++'s Run-time type information, or rtti. Compiling the library with "-fno-rtti" eliminated these errors.

The second problem was:

./lib.so: undefined reference to __cxa_pure_virtual'

Which was cause be the C compiler's inability to handle a virtual function from C++. Creating an stub function with extern "C" eliminated the error and allowed the project to compile.

I'm still confirming if the library is working correctly, but those changes seem to have corrected the errors.

Thanks for the help everyone.

Michael Curran
  • 131
  • 1
  • 3