简述
在 Windows 上,共享库由 .dll
表示;在 Linux 上,由 .so
表示。一个共享库中的符号被设计为导出的,以便客户端可以从中导入符号。
要使用共享库,除了 Qt之创建并使用共享库 中介绍的方式之外,Qt 还提供了一种机制,可以在运行时加载共享库,通过 QLibrary
来实现。
版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820
认识 QLibrary
QLibrary 用于在运行时加载共享库,一个完整的加载流程大概分为以下几步:
- 构造
QLibrary
实例 setFileName()
:指定共享库的文件名(也可以通过QLibrary
的构造函数来设置)load()
:动态加载共享库(isload()
检查加载是否成功)resolve()
:解析共享库中的符号(如果库还没有加载,那么resolve()
将隐式地尝试加载)unload()
:卸载共享库
QLibrary
有一个很强大的特性 - 在运行时对共享库提供了平台独立的访问。对于库路径,QLibrary
在内部会做以下处理:
- 如果文件名是绝对路径,则首先尝试加载该路径。若无法找到文件,则尝试使用不同平台的特定文件前缀(例如:Unix 和 Mac 上的 lib)和后缀(例如:Unix 上的
.so
、Mac 上的.dylib
、或 Windows 中的.dll
)的名称。 - 如果文件路径不是绝对的,那么
QLibrary
会修改搜索顺序,首先尝试系统特定的前缀和后缀,然后再指定文件路径。
这使得可以指定仅由其 basename(即:没有 .dll
或 .so
后缀)标识的共享库,因此相同的代码可以在不同的操作系统上工作。尽管如此,但仍建议尽量减少查找库的次数。
注意: 一个共享库可以被 QLibrary
的多个实例访问,加载完成后,库将一直保存在内存中,直到应用程序终止。在使用 unload()
卸载库时,如果 QLibrary
的其他实例使用了相同的库,那么调用将失败,并且只有当每个实例都调用 unload()
时才会卸载。
使用 QLibrary 的优点
在运行时使用 QLibrary
加载共享库,有很多优点:
- 无需使用
.h
头文件和.lib
文件,就可以编译应用程序。 - 只需将 dll 文件和可执行程序放在一起
- 可以在没有 dll 的情况下启动可执行程序,因为 dll 将在运行时(按需)加载。
- 有助于生成一个较小的可执行程序
创建共享库
和 Qt之创建并使用共享库 一样,在 Qt Creator 中创建两个项目:
- SharedLib:是一个 C++ 共享库项目,其中有一个导出符号。
- SharedLibClient:是一个 Qt 控制台应用程序,在运行时调用 SharedLib。
sharedlib_global.h 可以确保正确的宏能够被调用:
#ifndef SHAREDLIB_GLOBAL_H
#define SHAREDLIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(SHAREDLIB_LIBRARY)
# define SHAREDLIBSHARED_EXPORT Q_DECL_EXPORT
#else
# define SHAREDLIBSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // SHAREDLIB_GLOBAL_H
sharedlib.h 包含了导出的符号:
#ifndef SHAREDLIB_H
#define SHAREDLIB_H
#include "sharedlib_global.h"
extern "C" {
SHAREDLIBSHARED_EXPORT int subtract(int x, int y);
}
#endif // SHAREDLIB_H
sharedlib.cpp 包含了具体的实现:
#include "sharedlib.h"
int subtract(int x, int y)
{
return x - y;
}
注意: 对于要解析的函数名,必须将其导出为 C 函数。这意味着如果库是用 C++ 编译器编译的,那么函数必须被包装在一个 extern "C"
块中。
此外,还必须使用 Q_DECL_EXPORT
和 Q_DECL_IMPORT
从库中显式导出该函数。
在运行时加载共享库
创建一个简单的客户端(SharedLibClient) - Qt Console Application,它将使用 SharedLib 库中的 subtract()
函数。效果如下:
在 main.cpp 文件中,使用 QLibrary
在运行时加载共享库:
#include <QCoreApplication>
#include <QLibrary>
#include <qDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// SharedLibd.dll 与可执行程序位于同一目录
QLibrary lib("SharedLibd");
// 加载共享库
if (lib.load()) {
typedef int (*Fun)(int, int);
// 解析符号
Fun sub = (Fun) lib.resolve("subtract");
if (sub) {
int result = sub(5, 2);
qDebug() << result;
} else {
qDebug() << "Can not resolve subtract";
}
// 卸载共享库
lib.unload();
} else {
qDebug() << lib.errorString();
}
return a.exec();
}
在 Debug 模式下运行项目,结果会显示在控制台输出上。