说明

之前讨论的DLL的静态链接和动态连接都是基于 MSVC 编译器,但是 MinGW 似乎有另外一套类似但是不相同的机制。下文均在 windows 下使用 Qt Creator 中使用 MinGW 进行说明。

我们在新建库项目的时候有三种选项,如图所示:

三种类型分别是:共享库、静态链接库和Qt插件,之间区别以及和 MSVC 的库区别如下:

  1. 项目会根据类型不同生成 .dll 和 .a文件,这里的 .a 即类似 .lib,但是又不完全相同;
  2. 共享库 类似 msvc 的静态链接,构建最终生成 .a(类似.lib) 和 .dll,客户端编译时需要头文件和 .a,运行时需要 .dll;
  3. 静态链接库 则是另外一种新的机制,构建最终只生成 .a 文件,客户端调用时需要 .a 文件,运行时则不需要任何库文件,类似于客户端在编译时将库包进了自己的exe中;
  4. Qt插件不再多说,参考Qt插件系统文章,就是一种动态加载DLL的方法,但是又把加载的细节隐藏了;

综上所属,MingW 下的链接库相比于 MSVC,着实简单了很多,把内部的很多复杂的细节隐藏在Qt的内部系统中,对使用者来说,更加方便。

链接库的使用

下面就来简单介绍一下这些库的使用,Qt的插件不在讨论之列,请参考Qt插件系统文章。介绍中会忽略一些不重要的细节,我们认为你应该对C++和Qt有一个较深的认识,若没有,请自行去学习相关知识。同时,我们顺带简单介绍一些 .pro 文件的配置。

共享库

(1)创建共享库

共享库类似静态链接,生成.a文件和.dll文件。

按照正常流程新建库项目,类型选择 动态库,最终生成的项目列表中如下如所示:

可以看出,除了需要导出的类外,额外还有一个XXX_global.h的文件,文件代码如下:

  1. #ifndef FIRECONTROL_GLOBAL_H
  2. #define FIRECONTROL_GLOBAL_H
  3. #include <QtCore/qglobal.h>
  4. #if defined(FIRECONTROL_LIBRARY)
  5. # define FIRECONTROLSHARED_EXPORT Q_DECL_EXPORT
  6. #else
  7. # define FIRECONTROLSHARED_EXPORT Q_DECL_IMPORT
  8. #endif
  9. #endif // FIRECONTROL_GLOBAL_H

了解 MSVC 的dll导出的都能了解,这里其实是对 __declspec(dllexport)__declspec(dllimport) 进行一种巧妙的声明,因为导出需要使用export,导入需要使用import,为了避免在库和客户端中重复地进行export和import的声明,这里使用宏定义进行统一声明,详细说明可以参考DLL的导出和调用的文章。

在需要导出的类和方法前面使用 FIRECONTROLSHARED_EXPORT 声明即可,客户端调用时也需要将这个文件include进来。

当然,如果你对导出DLL的一个比较清晰的认识,也可以删除这个文件,自己定义。

(2)pro文件

  1. QT -= gui
  2. TARGET = FireControl
  3. TEMPLATE = lib #表示这是一个库项目
  4. DEFINES += FIRECONTROL_LIBRARY
  5. SOURCES += FireControlManager.cpp
  6. HEADERS += FireControlManager.h\
  7. firecontrol_global.h
  8. unix {
  9. target.path = /usr/lib
  10. INSTALLS += target
  11. }
  12. #上面为创建时自动生成,以下为新增
  13. DESTDIR = $$PWD/../SystemWindow/lib #最终编译文件的生成路径,包括.a和.dll
  14. DLLDESTDIR = $$PWD/../../../Service #dll文件的生成路径

(3)调用共享库

在调用端右击->添加库,选择生成 .a 文件,即可自动在 pro文件中添加加载设置。当然,也可以不适用GUI操作,直接修改pro文件以达到添加库的目的。

我们希望调用端和库项目分开构建,所以这里选择外部库

添加.a的库文件和头文件的包含目录,并配置一些链接方法

调用设置完成后,pro文件如下:

  1. QT += core gui
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. TARGET = SystemWindow
  4. TEMPLATE = app
  5. SOURCES += main.cpp\
  6. MainBench.cpp
  7. HEADERS += MainBench.h
  8. FORMS += MainBench.ui
  9. #以下即为自动生成的加载库设置
  10. win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lFireControl
  11. else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lFireControl
  12. else:unix:!macx: LIBS += -L$$PWD/lib/ -lFireControl
  13. INCLUDEPATH += $$PWD/../FireControl
  14. DEPENDPATH += $$PWD/../FireControl
  15. DESTDIR = $$PWD/../../../Service #目标生成路径

最后,可以在客户端使用库导出的类了,当然不要忘了添加头文件。

静态库

(1)创建静态库

静态最终只会生成 .a 文件。

创建库项目时,选择静态库,完成之后,项目目录的内容和目录中,除了没有入口的main函数外,其他都和普通项目没有什么区别,而真正的区别在于pro文件的配置中。

(2)pro文件

  1. QT -= gui
  2. TARGET = untitled
  3. TEMPLATE = lib #表示这是一个库项目
  4. CONFIG += staticlib #表示这是一个静态库
  5. SOURCES += untitled.cpp
  6. HEADERS += untitled.h
  7. unix {
  8. target.path = /usr/lib
  9. INSTALLS += target
  10. }
  11. DESTDIR = $$PWD/../SystemWindow/lib #生成路径

(3)调用静态库

调用方法和调用共享库类似,这里不做赘述,最终实际运行时不需要dll文件

总结

共享库和静态库各有各的优势,从最简单的层面上来看:

使用静态库可以将大项目区分开,即分模块显示项目,便于维护;

使用共项目也是如此,而且可以在不修改客户端的情况下,修改库内容的实现,只要接口不变,最终替换dll即可完成内容的改变。

但是看起来静态库有些鸡肋,具体还有哪些好处,留待日后发现。

QtCreator中使用链接库的更多相关文章

  1. linux c静态链接库与动态链接库

    库函数是我们编程的时候经常用到的,我们协作编程的时候可以将常用的函数封装成库供大家使用,这样能够提高大家的工作效率.对于库函数,它分为动态链接库和静态链接库.对于静态链接库我们必须是连接到可执行文件中 ...

  2. linux下C/C++编译时系统搜索 include 和 链接库 文件路径的指定

     C/C++程序在linux下被编译和连接时,GCC/G++会查找系统默认的include和link的路径,以及自己在编译命令中指定的路径.自己指定的路径就不说了,这里说明一下系统自动搜索的路径.   ...

  3. Linux中安装C++编译器codeBlock,并配置opencv链接库

    1.Linux中安装codeBlock https://blog.csdn.net/xinyunyishui/article/details/50967395 2.CodeBlock中的中文显示不完全 ...

  4. Linux中的共享链接库shared libraries

    可执行文件的静态链接和动态链接静态链接会将需要的库函数在编译时一并包含, 所以体积会比较大. 使用ldd命令查看可执行文件链接的库 $ ldd /sbin/ldconfig not a dynamic ...

  5. VS2010中如何将动态链接库改成静态链接库

    VS2010中如何将动态链接库改成静态链接库 VS2010静态编译生成的.exe可执行文件,可以免安装免DLL在其他电脑直接运行. 静态编译:就是在编译可执行文件的时候,将可执行文件需要调用的对应动态 ...

  6. Linux编程中链接库的使用

    链接库本质上是一段可执行的二进制代码,可以被操作系统载入内存执行.按加载的时机不同,链接库可以分为静态链接库和动态链接库. 静态链接库:编译过程中加载进可执行文件的库(静态库省去了运行时加载的消耗,但 ...

  7. 介绍静态链接库和动态链接库的差别,及在VC++6.0中的建立和使用

    首先介绍一下链接库:链接库分为动态链接库和静态链接库两种 LIB是静态链接库,在程序编译连接的时候是静态链接,其相应的文件格式是.lib. 即当程序採用静态链接库的时候..lib文件里的函数被链接到终 ...

  8. C运行时库(C Run-time Library)详解(提供的另一个最重要的功能是为应用程序添加启动函数。Visual C++对控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    一.什么是C运行时库 1)C运行时库就是 C run-time library,是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 2)C 语言是所谓的“ ...

  9. VC++中的C运行时库浅析(控制台程序默认使用单线程的静态链接库,而MFC中的CFile类已暗藏了多线程)

    1.概论 运行时库是程序在运行时所需要的库文件,通常运行时库是以LIB或DLL形式提供的.C运行时库诞生于20世纪70年代,当时的程序世界还很单纯,应用程序都是单线程的,多任务或多线程机制在此时还属于 ...

随机推荐

  1. 1196F - K-th Path

    题目链接: http://codeforces.com/problemset/problem/1196/F 题目大意::无向图,求任意两点第k短的路径 思路:按照边的大小,只保留前K个边,如果不连同的 ...

  2. Linux相关操作

    ssh配置秘钥 连接远程服务器时:需要用户持有“公钥/私钥对”,远程服务器持有公钥,本地持有私钥. 客户端向服务器发出请求.服务器收到请求之后,先在用户的主目录下找到该用户的公钥,然后对比用户发送过来 ...

  3. 19.SpringCloud实战项目-SpringCloud整合Alibaba-Nacos配置中心

    SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...

  4. 爬虫与反爬相生相克,道高一丈魔高一尺,如何隐藏ID(附代码)

    Python 反爬篇之 ID 混淆 作为爬虫的一方,如果知道了某个站点的数据自增 ID,那么就能轻而易举把整个站点都爬下来. 是不是有点耸人听闻,你去看很多大站例如油管.P 站等,他们都不会轻易把业务 ...

  5. Java 中正则表达式使用

    正则表达式基本用法: 测试代码: @Test public void test01() { String str = "adsfd##4324"; // 创建正则表达式对象 Pat ...

  6. Redis 的 maxmemory 和 dbnum 默认值都是多少?对于最大值会有限制吗?

    一.Redis 的默认配置 了解 Redis 的都知道,Redis 服务器状态有很多可配置的默认值. 例如:数据库数量,最大可用内存,AOF 持久化相关配置和 RDB 持久化相关配置等等.我相信,关于 ...

  7. PHP--关于上传文件大小的问题

    参考:https://www.cnblogs.com/jianqingwang/p/5863960.html https://blog.csdn.net/u013168253/article/deta ...

  8. phpcms 后台分页

    php 代码public function init() { $where='';//条件 $page = $_GET['page'] ? intval($_GET['page']) : '1'; $ ...

  9. 用百度AI平台接口实现OCR文字识别

    目录 一.接入指南 1.注册 2.登录 3.创建应用 二.安装接口模型 三.编写python代码 四.识别结果 一.接入指南 若想利用百度AI开放平台进行软件开发,首先应成为百度AI开放平台的开发者. ...

  10. 【Linux题目】第四关

    1. 如何过滤出已知当前目录下oldboy中的所有一级目录? 提示:不包含oldboy目录下面目录的子目录和隐藏目录,只要一级目录即可. 解答: ls -F|grep /   通过ls -F给目录后面 ...