我正在尝试将一些代码添加到需要使用C ++库的更大的C项目中。
C ++库使用标记为extern“C”的函数提供了一个包装器,可以访问库的功能
//Some C++ library
//mywrapper.h
#ifdef __cplusplus
extern "C" {
#endif
void wrapperFunction1( int width );
void wrapperFunction1( int height);
#ifdef __cplusplus
} // extern "C"
#endif
这可以毫无问题地编译g ++。
在制作C程序并包含mywrapper.h时,我不断发现引用vtable和cxa_pure_virtual的链接器错误:
undefined reference to `vtable for __cxxabiv1::__class_type_info'
undefined reference to `__cxa_pure_virtual'
在测试中,这些错误消失了,并且在我添加stdc ++库时允许程序编译,但这不是大C项目的选项。有没有办法编译C程序来访问没有这些错误和没有stdc ++的C ++库?并且错误的交易是指在C ++库内部并且未在mywrapper.h中引用的模块,那么为什么C程序甚至试图引用它们呢?
答案 0 :(得分:8)
C ++库依赖于标准C ++库(libstdc ++,链接器的-lstdc++
选项,如果通过g++
运行链接器则默认)。这是事实。没有什么可以做的。克服它。
包装器标头不引用这些符号,但库中的实际目标文件执行。因此需要定义它们,定义它们的方法是包含标准C ++库。
请注意,如果包装的库本身是动态的,它将知道它的依赖性,您不必动态指定与libstdc ++的链接。
答案 1 :(得分:3)
这是你要包装的C ++库需要stdc ++,而不是你的包装器。
您已经包装了C ++函数,以便它们可以从C中调用,但它们仍然在内部使用依赖于C ++标准库的库。如果您没有提供stdc ++,那么您正在使用的库将缺少其实现的一部分。除非你重写C ++库,否则无法绕过它。
答案 2 :(得分:1)
通常,C ++代码需要一定程度的运行时支持来处理特定的C ++特性。例如,有一个处理dynamic_cast<>()
的库函数。即使您不使用任何标准C ++库,您也需要这种语言支持libray。它通常包含在标准C ++库中,但专门针对gcc,此库可单独使用。也就是说,你可能会因为不包括libstdc++
而逃脱,但你不会逃脱包括这个库。目前我无法知道它是如何被调用的。我认为这是-lcxxabi
,但我不确定。
答案 3 :(得分:1)
完全有效的不包括libstdc++
一些警告。根据你在C ++代码中所做的事情(或者在这种情况下你正在包装的库),它可能希望底层运行时提供某些功能:
__cxa_pure_virtual
如果你有未实现的纯虚函数(例如,在纯抽象类中)main()
之前调用构造函数,在这不仅发生在您不包含libstdc++
库的情况下,而且还发生在已删除的库自定义版本上。
例如,Rowley Crossworks for ARM(嵌入式系统工具链)建议您自己编写__cxa_pure_virtual
错误处理程序。
答案 4 :(得分:0)
好的,我做了更多的研究,我偶然发现了答案,我有两个问题,首先是错误信息:
./lib.so: undefined reference to vtable for __cxxabiv1::__si_class_type_info'
./lib.so: undefined reference to `vtable for __cxxabiv1::__class_type_info'
这些与C ++的运行时类型信息或rtti有关。用“-fno-rtti”编译库消除了这些错误。
第二个问题是:
./lib.so: undefined reference to __cxa_pure_virtual'
原因是C编译器无法处理来自C ++的虚函数。使用extern“C”创建存根函数消除了错误并允许项目编译。
我仍然在确认库是否正常工作,但这些更改似乎已经纠正了错误。
感谢大家的帮助。