从 C 可执行文件加载动态库时收到错误C++"undefined symbol"

Receiving the error "undefined symbol" when loading C++ dynamic library from C executable

本文关键字:错误 C++ undefined symbol 可执行文件 加载 动态      更新时间:2023-10-16

我正在尝试为一个流行的程序编写一个插件,其代码和编译过程我无法控制。该程序是用 C 语言编写的。但是,我已经用C++编写了部分插件,因为我使用 QT5 库来实现图形功能。C 程序调用的函数是用 C 编写的。

当 C 程序尝试加载插件(共享库(时,会产生此错误:

dlopen('build/libfoo.so') failed: build/libfoo.so: undefined symbol: _ZTV13JoystickPanel

JoystickPanel是程序C++部分的一个类。

我尝试用 C 重写程序的某些部分,但错误不受影响。我知道我可以用 C 重写整个程序,但我宁愿不必切换到另一个对 C 更友好的 GUI 框架。我还在文本编辑器中打开了libfoo.so并搜索JoystickPanel,但它似乎被破坏为_ZN13JoystickPanel

我是否缺少任何编译器选项或解决方案?

我不知道_ZN13JoystickPanel是什么意思,因为它显然不是一个有效的C++名称。也许应该是_ZN13JoystickPanelE,这将转化为JoystickPanel。那肯定是符号名称,但无论如何都没有多大意义。你一定截断了一些东西:我尝试了很多,只是无法生成一个包含_ZN13JoystickPanel作为完整符号的对象文件。这只是一个前缀,应该有一个"后半部分"——有吗?

_ZTV13JoystickPanelJoystickPanel类的 vtable。它丢失了,因为您没有为JoystickPanel类的所有虚拟方法提供实现。最有可能的是,您没有正确调用 moc,或者忘记编译和链接其输出。

您至少需要为您的插件显示一个完整的构建脚本(.pro文件或CMakeLists.txt(。您还需要提供指向您的项目的 github 链接(我认为它是开源的(。

要在编译输出中找到的符号至少是_ZTV13JoystickPanelD#Ev- 虚拟析构函数,其中 # 是一个数字,_ZTV13JoystickPanel- 虚拟方法表,

当使用优化和/或 LTCG 编译时,这些符号可能不存在,但对它们的引用也将不存在。

您可能希望删除 build 文件夹并重新生成项目,以确保万无一失。qmake在生成它生成的 makefile 的依赖项方面很糟糕,所以如果你使用它,我建议切换到cmake+ninja.

显然,我忘记将#include "moc_controller.cpp"行放在需要它的文件的底部。

对于在CMake上使用Qt时遇到此问题的其他人,请考虑确保添加了正确的行。