为什么我无法使用 gcc 链接具有 C 接口的混合 C/C++ 静态库?

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

本文关键字:混合 接口 C++ 静态 链接 gcc 为什么      更新时间:2023-10-16

我有一个C/c++混合库。

在外部,它使用extern C提供了一个C接口。内部有模板和类。用"ar"创建库没有任何问题。文件名为lib -client.a。

然而,当使用gcc(不是g++)链接.a文件时,我得到了很多错误,看起来像这样:

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'
...

我的编译/链接行是这样的:

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

test2是我的测试工具

当我使用g++时,这个问题不会发生。但是,我将把这个库接口到用gcc编译的C项目中。我该怎么解决这个问题?它的原因是什么?

编辑:

虽然我没有使用标准的c++库,但它显然需要一些像operator new/delete之类的东西,并且内部有异常。

我链接这个东西对Xen管理程序,所以我不确定我有什么选择,但完全重写这个东西,或者也许尝试编译Xen与g++代替?

解决问题的最简单方法是与g++链接;这会得到正确的库。

问题是c++有很多C没有的要求,并且在调用main()之前做了更多的工作来确保事情被正确初始化。

如果你坚持与C编译器链接,至少你必须在你的链接命令中包含c++支持库

您的c++库在内部仍然是一个c++库,这意味着它包含对来自c++标准库的各种管理函数的外部引用。为了解决这些链接,你必须链接c++标准库的最终可执行文件。gcc不会自动为您做这件事。要么显式地为gcc提供c++标准库,要么使用g++编译器。

归档文件仍然只是一堆目标文件(.o),所以当将它们链接到可执行库或共享库时,您仍然需要链接g++以将符号解析到c++运行时(就像您在错误消息中看到的那样)。

要使C函数具有C链接,将它们包装在extern "C"块中就足够了。事情可能会变得更复杂,例如Windows,它有无数的链接宏(STDCALL, WINAPI等),扩展到其他东西(一些编译器特定的),如__stdcall, __declspec(export)等。

您看到的错误似乎是由于缺少与标准c++库的链接而出现的,该库具有operator new, operator delete等的符号定义。试着连接stdc++gcc $(CFLAGS) $(INCLUDES) test2.c libo-client.a -o test2 -lstdc++。更好的选择是由Jonathan Leffler建议使用g++而不是gcc

用c++编写可以在C中使用的东西,而不需要c++需要的任何额外的东西是非常困难的。甚至可能依赖于编译器。您的库需要c++运行时,并且在程序中调用main()之前初始化c++运行时可能需要特殊的支持。当你链接C文件时,你的chimaera仍然是一个c++程序,即使它是main()和库外的其他所有东西。