简述:
在 Windows 中,有动态链接库(DLL - Dynamic Link Library);在 Linux 中,有共享库(Shared Library),它们是相同的!
由于平台和编译器的差异,输出的库文件也不同:
在 Windows 中,MinGW 将输出 .a 和 .dll;MSVC 将输出 .lib 和 .dll
在 Linux 中,MinGW 将输出 .so、.so.1、.so.1.0 和 .so.1.0.0 - .lib
.a 和 .so 是导入库,它们有助于将我们的代码链接到库中,并且在构建文件时需要
创建共享库:
要创建一个共享库,需要执行以下几个步骤:
新建文件项目—>选择library—>选择C++库:
选择“共享库”,再输入项目名称(这里以SharedLib为例),选择创建路径:
选择编译方式,这里以msvc2017 64bit、MinGW 32bit为例:
选择需要的模块(默认勾选“QtCore”,如果需要其他模块,请自行勾选。例- 如:界面需要依赖 QtWidgets)。
自行定义类名,点击下一步再点击完成,进入项目文件:
项目文件
在项目创建完成之后,Qt Creator 会帮我们生成一系列相关文件,目录结构如下:
这里,同时出现了一个非常重要的文件 - {projectName}_global.h,这是 Qt Creator 帮我们创建的,内容如下:
符号 - 函数、变量或类 - 包含在供客户端(例如:应用程序或其他库)使用的共享库中,必须以一种特殊的方式标记。这些符号被称为公共符号,它们被导出或公开可见。
在编译共享库时,必须将其标记为导出。为了在客户端使用共享库,一些平台可能需要一个特殊的导入声明。
为此,Qt 提供了两个特殊的宏:
Q_DECL_EXPORT:当编译共享库时,必须将其添加到使用的符号声明。
Q_DECL_IMPORT:当编译一个(使用了该共享库)客户端时,必须将其添加到使用的符号声明。
所以,要确保正确的宏能够被调用(无论是编译共享库本身,还是在客户端使用共享库),通常通过添加一个特殊的头文件({projectName}_global.h)来解决,这就是 sharedlib_global.h 存在的原因。
pro文件中的内容:
TARGET:指定库的名称
TEMPLATE:模板的意思,将其指定为 lib,是要告诉 qmake 我们需要生成的是一个库文件(app 为可执行程序)。
DEFINES:用于定义编译选项
CONFIG:用于编译控制
生成共享库
生成的库中只有一个简单的类定义,为了便于使用,为其添加一些简单的函数:
sharedlib.h 内容如下:
sharedlib.cpp 内容如下:
构建(不运行)项目,会生成相应的 .lib 和 .dll 文件。这里使用MinGW 32bit的Debug模式编译:(注意:MinGW编译生成的库,后续只能给使用MinGW编译的项目使用;如果项目使用msvc编译,同样库也需要msvc编译生成)
在debug文件夹中可以看到,生成了所需要的.a和.dll文件:
应用程序与共享库链接
为了验证共享库的使用,创建一个简单的客户端(这里项目名使用SharedLibClient):
下一步,选择MinGW 32bit编译:
项目创建成功后,将刚才生成的共享库组织到项目文件中:
首先,创建一个文件夹(这里用3rdparty):
然后,在3rdparty文件夹中创建两个文件夹(include和lib):
将共享库内容中的.h文件复制到include文件夹中:
将共享库内容中的.a和.dll文件复制到lib文件夹中:
将include文件夹的内容添加到qt项目中,生成如下目录:
右键项目,选择“添加库”:
选择链接的库类型,这里选择“外部库”:
添加库中点击“浏览”,选择.a文件添加:
这里选择windows:
完成后,.pro文件会自动添加以下代码:
$$PWD 用于指定包含 .pro 文件的目录的完整路径
INCLUDEPATH - 指定编译项目时应该被搜索的 #include 目录
LIBS - 指定链接到项目中的库列表
测试共享库
main.cpp 内容如下:
运行程序,效果如下图所示: