QLibrary 对象的实例对单个共享对象文件(库文件)进行操作。QLibrary 以独立于平台的方式提供对库中功能的访问。可以在构造函数中传递文件名,也可以使用 setFileName() 显式设置它。加载库时,除非文件名具有绝对路径,否则QLibrary 将搜索所有系统特定的库位置(例如 Unix 上的 LD_LIBRARY_PATH)。
如果文件名是绝对路径,则首先尝试加载此路径。如果找不到文件,QLibrary 会尝试使用不同平台特定的文件前缀(如 Unix 和 Mac 上的“lib”)和后缀(如 Unix 上的“.so”、Mac 上的“.dylib”或“.dylib”、在 Windows 上的“.dll”)。
如果文件名不是绝对路径,那么 QLibrary 会修改搜索顺序以首先尝试系统特定的前缀和后缀,然后是指定的文件路径。这使得指定仅由其基本名称(即没有后缀)标识的共享库成为可能,因此相同的代码可以在不同的操作系统上运行,但仍然可以最大限度地减少尝试查找库的次数。
因为 QLibrary 会自动查找具有适当后缀的文件,所以建议在文件名中省略文件的后缀。
QLibrary 的多个实例可用于访问同一个物理库。加载后,库将保留在内存中,直到应用程序终止。
QLibrary 的典型用途是解析库中的导出符号,并调用该符号表示的 C 函数。这被称为“显式链接”,与“隐式链接”相反,当将可执行文件链接到库时,这是由构建过程中的链接步骤完成的。
以下代码片段加载一个库,解析符号“mysymbol”,并在成功时调用该函数。如果出现问题,例如库文件不存在或符号未定义,函数指针将为 nullptr 且不会被调用。
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
符号必须从库中导出为 C 函数,resolve() 才能工作。 这意味着如果库是使用 C++ 编译器编译的,则该函数必须包含在 extern "C" 块中。 在 Windows 上,这也需要使用 dllexport 宏。 为方便起见,如果只想调用库中的函数而不先显式加载库,则可以使用静态 resolve() 函数:
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) QLibrary::resolve("mylib", "mysymbol");
if (myFunction)
myFunction();
1、enum QLibrary::LoadHint:此枚举描述了可用于更改库加载(load())时处理方式的可能标志。这些值指示加载库时如何解析符号。默认情况下,这些标志都没有设置,并且不会导出外部符号以在其他动态加载的库中解析。在库加载后设置标志无效,并且 loadHints() 不会反映标志更改。
1、QLibrary(const QString &fileName, const QString &version, QObject *parent = nullptr)
将加载由 fileName 和完整版本号 version 指定的库。版本号在 Windows 上被忽略。
2、QLibrary(const QString &fileName, int verNum, QObject *parent = nullptr)
将加载由 fileName 和主要版本号 verNum 指定的库。版本号在 Windows 上被忽略。
3、QLibrary(const QString &fileName, QObject *parent = nullptr)
将加载由 fileName 指定的库。
4、~QLibrary()
销毁 QLibrary 对象。除非显式调用 unload(),否则库将保留在内存中,直到应用程序终止。
5、QString errorString()
返回一个文本字符串,其中包含对发生的最后一个错误的描述。当前,仅当 load()、unload() 或 resolve() 由于某种原因失败时才会设置 errorString。
6、【静态】bool isLibrary(const QString &fileName)
fileName 是否具有可加载库的有效后缀。
Unix 上的尾随版本号将被忽略。
7、bool isLoaded()
库是否已加载。
8、bool load()
加载库,如果库加载成功则返回true;否则返回false。由于 resolve() 总是在解析任何符号之前调用此函数,因此没有必要显式调用它。
9、QFunctionPointer resolve(const char *symbol)
【静态】QFunctionPointer resolve(const QString &fileName, const char *symbol)
【静态】QFunctionPointer resolve(const QString &fileName, int verNum, const char *symbol)
【静态】QFunctionPointer resolve(const QString &fileName, const QString &version, const char *symbol)
返回导出的符号符号的地址。如有必要,将加载库。 如果无法解析符号或无法加载库,则该函数返回 nullptr。
QFunctionPointer 是 void (*)() 的 typedef,指向不带参数并返回 void 的函数的指针。
例:
添加一个库工程。内容如下:
testlibrary.h
#ifndef TESTLIBRARY_H
#define TESTLIBRARY_H
extern "C" __declspec(dllexport) int sum(int a, int b);
#endif
testlibrary.cpp(必须有cpp文件)
#include "testlibrary.h"
int sum(int a, int b)
{
return a+b;
}
创建一个工程导出整个库中的函数:
using Fun = int (*)(int, int);
int main(int argc, char *argv[])
{
QLibrary lib("testLibrary");
// Fun fun = reinterpret_cast<Fun>(QLibrary::resolve("testLibrary","sum"));
Fun fun = reinterpret_cast<Fun>(lib.resolve("sum"));
if (fun)
{
qDebug()<<fun(100,200);
}
else
{
qDebug()<<lib.errorString();
}
}
10、void setFileNameAndVersion(const QString &fileName, int versionNumber)
将 fileName 属性和主要版本号分别设置为 fileName 和 versionNumber。在 Windows 上忽略 versionNumber。
void setFileNameAndVersion(const QString &fileName, const QString &version)
将 fileName 属性和完整版本号分别设置为 fileName 和 version。在 Windows 上忽略version 。
11、bool unload()
如果可以卸载库,则卸载库并返回 true;否则返回false。
这在应用程序终止时自动发生,因此通常不需要调用此函数。
如果 QLibrary 的其他实例正在使用相同的库,则调用将失败,并且只有在每个实例都调用了 unload() 时才会发生卸载。
注意,在 Mac OS X 10.3 (Panther) 上,无法卸载动态库。