Qt编译和链接错误
修改 widget.cpp,添加一行新代码和一个新头文件,如下所示:
#include widget.h #include ui_widget.h #include QtTest/QTest //new header file Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) ui- setupUi(this); qsleep(1000); //new code Widget::~Widget() delete ui; }
QtTest/QTest 是 Qt 单元测试模块的头文件,它里面有一个睡眠函数 void QTest::qSleep(int ms),让当前程序睡眠参数指定的 ms 毫秒。上面示范故意写错了函数名,S 大写变成了小写 s 。
点击运行按钮,或者按下 Ctrl+R 快捷键,就可以看到如下图所示的编译错误:
![Qt Creator报错信息](http://ytso-blog-oss-img.oss-cn-beijing.aliyuncs.com/wp-content/uploads/2021/07/20/20210720_60f63eba1f540.gif)
下面的输出面板自动显示了编译时的错误, qsleep 没有在当前作用域中声明;在源代码编辑器 qsleep(1000) 这一行的行首有红色背景的感叹号,标出了这行有错误发生。
接着我们把睡眠函数改成正确的 qSleep,再次点击运行按钮,或者按下 Ctrl+F5 快捷键,发现还有错误:
![Qt Creator报错信息](http://ytso-blog-oss-img.oss-cn-beijing.aliyuncs.com/wp-content/uploads/2021/07/20/20210720_60f63eba3b32a.gif)
还是提示 qSleep 没有声明,但这回给出的错误描述不一样,在问题面板的 note 字样一行可以看到提示 QTest::qSleep ,这次出错是因为 qSleep 函数在名字空间 QTest 里面声明的,如果要用这个函数得加名字空间前缀,或者用 using 语句引入名字空间。我们这里直接给出错的行加名字空间前缀,变成:
QTest::qSleep(1000);
对于编译时错误,常见的就是写错函数名或变量名、类名,没有包含正确的头文件,没有使用正确的名字空间或类前缀等。如果是 Qt 自己的模块或类,直接包含相应的头文件就可以了。
如果是非 Qt 库的头文件,可以在 pro 文件里添加 INCLUDEPATH 变量,比如:
INCLUDEPATH += E:/mylibs/extra headers
INCLUDEPATH += /home/username/extra headers
上面第一个是 Windows 路径包含,第二个是 Linux/Unix 路径包含。添加包含路径之后,可以在项目源代码里直接包含头文件名:
#include extra.h
QtCreator 编辑器支持包含的文件名补全,可自动搜索 Qt 库标准路径和额外包含路径里的头文件。
按照上面的说明修改好代码之后,我们就来验证一下吧。再次点击运行按钮,或者按下 Ctrl+R 快捷键,竟然还会有报错信息:
这回也是撞见鬼了,就改了一行代码,还是往正确了改,怎么蹦出十几条错误?最后一条错误描述说明链接器 ld 返回错误了,这是链接目标文件和库文件时出了错误,无法生成最终的可执行程序。问题面板列的十几条错误,就最后倒数第二个是指向 widget.cpp 里的睡眠函数的,报的错误是error: undefined reference to `_imp___ZN5QTest6qSleepEi ,这是未找到真实的函数引用(定义)的意思,`_imp___ZN5QTest6qSleepEi 是函数 QTest::qSleep 在编译之后的库文件里的引用名字,链接时找不到引用,通常是没有链接正确的 *.a 库声明文件(Linux 上直接链接到 *.so )。
之前提到 qSleep 是 Qt 单元测试模块里的函数,需要为当前项目添加对应的 Qt 模块,编译链接时 qmake 才会为项目添加正确的头文件目录和链接库文件。上面源代码实际没有问题,出问题的是 HelloWorld.pro 文件。在左边项目视图打开 HelloWorld.pro 文件,编辑如下(注释部分已去掉):
QT += core gui testlib
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = HelloWorld
TEMPLATE = app
SOURCES += /
main.cpp /
widget.cpp
HEADERS += /
widget.h
FORMS += /
widget.ui
上面就是为项目添加了 Qt 模块 testlib ,使用单元测试模块,就应该在 pro 文件里的QT +=一行里添加 testlib ,然后保存项目文件。
QtCreator 会稍微花些时间重新解析 pro 文件,然后我们点击主菜单菜单 构建 重新构建项目 HelloWorld ,对项目进行重新构建。一般如果修改了 pro 文件,需要手动重新构建项目,避免一些莫名其妙的构建错误(如找不到 WinMain 函数引用)。另外,删除构建目录如 build-HelloWorld-Desktop_Qt_5_9_0_MinGW_32bit-Debug ,然后点击构建或运行按钮,也能实现重新构建项目。如果遇到莫名其妙的构建问题,可以尝试这两种方法。
运行正确编译链接的目标程序,主界面弹出之前会明显感觉到有 1 秒多的迟钝,这是因为我们在主界面构造函数里睡眠了 1000 毫秒,也就是 1 秒。
为 Qt 添加库文件对于链接时错误,最常遇到的就是本小节里的 undefined reference to **** 链接错误,通常是没有链接到正确的库文件,对于 Qt 自己的库模块,只需要在 pro 文件里QT += 一行末尾加上对应的模块名字,qmake 就会在编译链接时为项目添加正确的包含路径和链接库文件。
对于非 Qt 模块的库文件,通常是在项目文件 pro 里添加 LIBS 变量行,一般添加规则是:
LIBS += 库文件路径全名
LIBS += -L库文件路径 -l库文件短名
这两种写法都可行。库文件短名是指去掉打头的 lib 和扩展名,只留下中间的,比如 libextra.a 或 libextra.so 都写成 -lextra (Linux 里优先链接动态库 .so,Windows 里不用管这些)。
下面是一些例子:
LIBS += C:/mylibs/extra libs/extra.lib
LIBS += C:/mylibs/extra libs/libextra.a
LIBS += -L/home/user/extra libs -lextra
上面示范的是有空格的路径,必须加双引号才能找到正确位置,如果没空格可以省去双引号。因此不要在库的全路径里出现空格或特殊字符,那纯粹是找麻烦。
示例的第一个 是 VC 库文件用法,第二个是 MinGW 动态链接库引用库 .a 文件或静态库 .a 文件用法,第三个是 Linux/Unix 里的链接库用法,MinGW 也可以采用这种写法。
这些东西在以后的章节里会有些涉及,对于纯 Qt 程序目前不用操心的,这里只是提点一下,等到用的时候再查文档就行了。
22445.html
htmllinuxQtSTL链接库相关文章
- Qt动画播放之QMovie类[通俗易懂]
- 来自Qt交流群的群友提问
- Qt官方示例-迷你网页浏览器
- Qt官方示例-缓和曲线
- Qt——Qt Creator编程软件常用的快捷键及Qt帮助文档的使用总结
- Qt Qml 实现多屏、低延时播放超高清8K直播
- 使用 Qt 连接远程 MySQL 数据库(qt连接远程mysql)
- Qt QStringListModel用法详解
- Linux 下 Qt 调试技巧(qt调试linux)
- Linux安装Qt的步骤指导(linux怎么安装qt)
- Qt蓝牙编程指南:在Linux系统上使用Qt开发蓝牙应用程序(qt蓝牙编程linux)
- Linux上静态编译Qt应用实现方案(linux静态编译qt)
- 开发linux下 Qt 图形界面开发实践(linux下qt图形界面)
- 实现快速 Linux Qt 配置方案(linuxqt配置)
- qt实现mysql远程连接:快速入门指南(qt远程连接mysql)
- Qt与Oracle数据库的高效结合(qt数据库oracle)
- Qt运行于Linux系统下的文件操作(Qtlinux文件)
- Linux Qt解决您的开发困扰(linuxqt帮助)
- 在Linux下探索Qt程序的奥秘(linux下运行qt程序)
- 的整合『使用 Qt 与MySQL实现创新性的数据库应用』(qt与mysql)
- Linux平台上Qt程序开发发布实践(linuxqt程序发布)
- Linux下Qt移植的探索与实践(linux移植qt)
- 集成开发Linux与Qt集成开发:实现无缝交互(linux与qt)
- 利用Qt轻松操作Oracle数据库(qt操作oracle)
- 提高数据处理效率:探究Qt与MySQL数据库的结合应用(qt与mysql数据库)
- QT开发MSSQL数据库技术实现(qt mssql)
- 界面让Linux拥有Qt完美图形界面的魅力(linux qt 图形)