Qt+OpenCV项目GCC链接错误:未定义QPushButton::hitButton引用
Qt+OpenCV链接错误问题解答
问题背景
在Fedora 35 x64系统中,使用本地安装的Qt 5.14.2、OpenCV 4.3及GCC 11开发Qt项目时,出现链接错误。
链接命令及错误信息
g++ -Wl,-rpath,/home/qt/Qt/5.14.2/gcc_64/lib -o QtOpenCVCompatibleTest main.o mainwindow.o moc_mainwindow.o -L/home/qt/Qt/5.14.2/gcc_64/lib -lopencv_core -lopencv_videoio -lopencv_highgui /home/qt/Qt/5.14.2/gcc_64/lib/libQt5Widgets.so /home/qt/Qt/5.14.2/gcc_64/lib/libQt5Gui.so /home/qt/Qt/5.14.2/gcc_64/lib/libQt5Core.so -lGL -lpthread /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/11/../../../../lib64/libopencv_highgui.so: undefined reference to `QPushButton::hitButton(QPoint const&) const@Qt_5'
项目.pro文件相关配置
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets INCLUDEPATH += /usr/include/opencv4/ LIBS += -L/home/qt/Qt/5.14.2/gcc_64/lib -lopencv_core -lopencv_videoio -lopencv_highgui
符号检查结果
通过nm命令检查本地Qt 5.14.2的libQt5Widgets.so,发现仅存在父类及其他子类的hitButton方法:
nm -gDC /home/qt/Qt/5.14.2/gcc_64/lib/libQt5Widgets.so | grep hitButton 0000000000331a00 T QToolButton::hitButton(QPoint const&) const@@Qt_5 00000000002e4990 T QRadioButton::hitButton(QPoint const&) const@@Qt_5 000000000024e060 T QAbstractButton::hitButton(QPoint const&) const@@Qt_5 000000000025d840 T QCheckBox::hitButton(QPoint const&) const@@Qt_5
疑问解答
1. C++早期绑定在链接器中的工作机制为何?是否是OpenCV编译所用Qt版本不同?
C++中,非虚函数是早期绑定(静态绑定),编译器在编译阶段就确定调用的函数符号,不会在运行时动态解析。如果子类没有重写父类的非虚函数,调用子类对象的该函数时,编译器会直接生成调用父类函数的代码,符号名也是父类的函数名;只有虚函数才会通过虚表在运行时动态查找。
这里的核心问题是:你系统中的libopencv_highgui.so是用更高版本的Qt(5.15及以上)编译的——在Qt 5.15及以后的版本中,QPushButton重写了hitButton这个虚函数,而Qt 5.14.2中QPushButton并未重写该函数,因此你的Qt库中不存在QPushButton::hitButton的符号,导致链接失败。
2. GCC链接命令的正确调用顺序是什么?是否Qt库应放在最后?
GCC链接器的规则是:依赖库要放在被依赖库的前面。也就是说,如果A库依赖B库,那么A库的链接参数要写在B库前面。
你的当前链接命令中,OpenCV库(依赖Qt库)写在Qt库前面,这是符合规则的,顺序没问题。如果反过来,会出现大量Qt相关的未定义符号,但这不是当前问题的根源。
3. 如何解决该链接错误?
有三种可行的解决方案:
- 升级Qt版本:将本地Qt升级到5.15及以上版本,此时
libQt5Widgets.so会包含QPushButton::hitButton的符号,直接匹配OpenCV的依赖。 - 重新编译OpenCV:使用本地的Qt 5.14.2重新编译OpenCV 4.3,确保OpenCV链接的Qt版本与项目使用的版本一致,生成的
libopencv_highgui.so会依赖QAbstractButton::hitButton符号,避免版本不兼容问题。 - 替换OpenCV库:寻找一个用Qt 5.14.x编译的OpenCV 4.3版本替换系统中的库,或者通过设置
LD_LIBRARY_PATH环境变量,让程序优先加载你自行编译的兼容版本。
内容的提问来源于stack exchange,提问作者Patrick Z
相关产品推荐
相关产品推荐

