一个QLibrary对象的实例操作一个共享的对象文件(我们称之为“库”)。在Qt中,QLibrary以平台独立的方式提供了对库中功能的访问。我们可以在QLibrary
构造函数中传递库文件名,也可以使用setFileName()显式地设置库文件名。当加载库时,QLibrary会搜索操作系统下特定的库位置(例如Unix系列操作系统上的LD_LIBRARY_PATH)。如果文件名使用了绝对路径,那么又会有不同的搜索形式。
如果文件名是绝对路径,则会先尝试加载该路径下的库。如果找不到库文件,QLibrary会使用不同平台下特定的文件前缀(如Unix和Mac上的“.lib”、Unix上的".so"。Mac上的“dylib”,Windows上的“.dll”)。
如果文件路径不是绝对的,那么QLibrary则会修改搜索顺序,首先尝试搜索系统特定的前缀和后缀,然后搜索指定的文件路径。
好啦,上文则是QLibrary的大概使用方法和相关规则。
一些常用的成员操作
在实际开发中,较常使用的函数是load()
,该函数用于动态加载库文件,然后我们则使用isLoaded()
检查加载是否成功。有效的库文件后缀如下表所示:
再库文件被加载后,我们需要使用resolve()
函数去解析库中的符号。如果库没有被加载,resolve()函数还会隐式尝试去加载它。
在实际使用中,我们可以使用多个QLibrary实例来访问相同的库。一旦库被加载,它将一直保存在内存中,直到应用程序终止才会销毁。我们还可以尝试使用unload()
卸载一个库,但如果QLibrary的其他实例正在使用该库,该函数将会执行失败。
QLibrary的典型用法是解析库中导出的符号,并调用该符号所代表的使用C语言编写的函数。例如下面的代码片段会加载一个库,并解析“mysymbol”符号,并在解析成功后调用该函数。如果出现错误,例如库文件不存在或符号没有定义,此刻函数指针将为nullptr,那么该函数则不会被调用。
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
以上代码片段中:首先使用QLibrary加载一个库;然后定义了一个函数指针MyPrototype
类型;接着通过QLibrary的resolve()
函数解析库中的符号,并将结果赋值给myFunction,如果myFunction不为nullptr,则调用该函数。
【注意】对于使用QLibrary
来进行库文件的解析,符号必须从库中导出是一个C语言编写的函数,这样才能使resolve()能得以正常解析。这意味着:如果标准库是用c++编译器编译的,函数则必须封装在extern "C"块中。例如下列的使用场景:
首先,resolve()
函数原型如下:
QFunctionPointer QLibrary::resolve(const char *symbol)
此成员函数返回导出符号的地址。如果符号无法解析或库无法加载,则该函数返回nullptr。
例如下列代码:
typedef int (*AvgFunction)(int, int);
AvgFunction avg = (AvgFunction) library->resolve("avg");
if (avg)
return avg(5, 8);
else
return -1;
在上述代码中,avg
符号必须从库中导出为C函数。在Windows中,还必须使用__declspec(dllexport)
编译器指令显式地从DLL中导出该函数:
extern "C" MY_EXPORT int avg(int a, int b)
{
return (a + b) / 2;
}
MY_EXPORT
宏定义如下:
#ifdef Q_OS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
载入标志
在使用QLibrary
载入库的时候,我们可以使用setLoadHints()
设置载入标志。该标志由enum QLibrary::LoadHint
枚举来定义,这些值表示在加载库的时候如何解析符号,具体类型和含义如下表所示:
常量 | 数值 | 描述 |
---|---|---|
QLibrary::ResolveAllSymbolsHint | 0x01 | 在加载库时解析库中的所有符号,而不仅仅是在调用resolve()时解析。 |
QLibrary::ExportExternalSymbolsHint | 0x02 | 导出库中未解析、外部符号,以便在其他动态加载的库中进行解析。 |
QLibrary::LoadArchiveMemberHint | 0x04 | 允许库的文件名指定存档文件中的特定对象文件。如果给出了这个提示,那么库的文件名包含一个路径,它是对存档文件的引用,后面的名称是对存档成员的引用。 |
QLibrary::PreventUnloadHint | 0x08 | 如果调用close(),防止从地址空间中卸载库。如果在后续调用open(),库的静态变量不会被重新初始化。 |
QLibrary::DeepBindHint | 0x10 | 指示链接器在解析加载库中的外部符号时,优先选择在加载库中的定义,而不是加载应用程序中导出的定义。此选项仅支持linux平台 |
注意
在实际使用
QLibrary
的过程中,其库需要是使用C语言编译器编译导出的接口。