<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class QLibraryPrivate
{
public:
#ifdef Q_OS_WIN
HINSTANCE
#else
void *
#endif
pHnd; // 库的句柄。当库被加载load成功后,会被设置为有效值;否则,是Null
QString fileName, qualifiedFileName; // 库文件名
QString fullVersion;
bool load(); // 加载库,内部通过与系统相关的函数 load_sys() 实现
bool loadPlugin(); // loads and resolves instance // 内部会调用load,然后设置 instance 函数
bool unload(UnloadFlag flag = UnloadSys); // 卸载库,内部通过与系统相关的函数 unload_sys() 实现
void release(); // 释放库,内部会调用 类QLibraryStore 的 releaseLibrary() 方法
QFunctionPointer resolve(const char *); // 将库中的符号实例化,内部通过与系统相关的函数 resolve_sys() 实现
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = 0);
...
QtPluginInstanceFunction instance;
// instance是产生插件实例的函数,返回QObject*。这个函数在构造函数中被初始化为NULL。
// 插播一句,在Qt编译出来的插件库文件(xxx.so)中,用 "nm xxx.so -D" 命令列出其中的符号,
// 可以看到其中有 qt_plugin_instance 和 qt_plugin_query_metadata 符号,这两个符号
// 都是 Qt 在编译插件时由MOC系统将Q_PLUGIN_METADATA 宏展开后生成的,他们是两个函数,
// 其中qt_plugin_instance 函数会在插件加载load()成功后,赋值给 QLibraryPrivate类的instance(这一步是在 loadPlugin() 函数中实现的),
// 这样就能直接通过 QLibraryPrivate::instance() 访问到插件的实例了。
// 而另一个函数qt_plugin_query_metadata则用于获取插件的元信息metaData
QPointer inst; // 插件的实例,只有当这个QLibraryPrivate对象属于一个QPluginLoader对象时,QPluginLoader::instance()函数中
// 才会设置这个 inst, 参见下面插入的几行代码。另外,在 unload 函数中,inst 会被delete掉
/* QObject *QPluginLoader::instance()
{
if (!isLoaded() && !load())
return 0;
if (!d->inst && d->instance)
d->inst = d->instance(); // 这一步设置 inst
return d->inst.data();
} */
QJsonObject metaData; // 库的元信息
...
QLibrary::LoadHints loadHints; // 加载策略
void updatePluginState(); // 更新库的插件状态,内部会设置下面的成员变量 pluginState
bool isPlugin(); // 调查这个库是不是插件,内部会读取成员变量 pluginState
static inline QJsonDocument fromRawMetaData(const char *raw) { // 从二进制数据中获取QJson。插件/库的元数据就从此而来
raw += strlen("QTMETADATA ");
// the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h),
// but doesn't include the size of the header (8 bytes)
QByteArray json(raw, qFromLittleEndian(*(uint *)(raw + 8)) + 8);
return QJsonDocument::fromBinaryData(json);
}
private:
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints);
~QLibraryPrivate(); // 构造与析构
void mergeLoadHints(QLibrary::LoadHints loadHints); // 设置加载策略
bool load_sys(); // 与系统相关的加载、卸载或 resolve函数,内部会调用系统API
bool unload_sys();
QFunctionPointer resolve_sys(const char *);
/// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded
QAtomicInt libraryRefCount; // 引用计数
/// counts how many times load() or loadPlugin() were called
QAtomicInt libraryUnloadCount; // 加载计数。虽然从变量名来看是卸载计数,但从注释中可以看出是加载计数
enum { IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState; // 标记这个库是不是一个插件,构造函数中初始化为 MightBeAPlugin,即不确定状态。
friend class QLibraryStore;
};
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
return QLibraryStore::findOrCreate(fileName, version, loadHints);
}
QLibraryPrivate::~QLibraryPrivate()
{
}
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
loadHints(loadHints),
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{
if (canonicalFileName.isEmpty())
errorString = QLibrary::tr("The shared library was not found.");
}
QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
return QLibraryStore::findOrCreate(fileName, version, loadHints);
}
QLibraryPrivate::~QLibraryPrivate()
{
}
static QLibraryStore *qt_library_data = 0;
static bool qt_library_data_once;
QLibraryStore *QLibraryStore::instance()
{
if (Q_UNLIKELY(!qt_library_data_once && !qt_library_data)) {
// only create once per process lifetime 每个进程的生命周期中只创建一次QLibraryStore
qt_library_data = new QLibraryStore;
qt_library_data_once = true;
}
return qt_library_data;
}
QLibraryStore::~QLibraryStore()
{
qt_library_data = 0; // 这个类的析构函数只是清除一个全局指针,从这里也反映出这个类就是为专门全局静态变量qt_library_data准备的
}
inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints)
{
QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance();
// check if this library is already loaded
QLibraryPrivate *lib = 0;
if (Q_LIKELY(data)) {
lib = data->libraryMap.value(fileName);
if (lib)
lib->mergeLoadHints(loadHints);
}
if (!lib)
lib = new QLibraryPrivate(fileName, version, loadHints);
// track this library
if (Q_LIKELY(data))
data->libraryMap.insert(fileName, lib);
lib->libraryRefCount.ref(); // 库的引用计数加 1
return lib;
}
inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
{
QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance();
if (lib->libraryRefCount.deref()) {
// still in use
return;
}
// no one else is using
Q_ASSERT(lib->libraryUnloadCount.load() == 0);
if (Q_LIKELY(data)) {
QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
Q_ASSERT(lib == that);
Q_UNUSED(that);
}
delete lib; // QLibraryPrivate的析构函数中什么也不做
}
inline void QLibraryStore::cleanup()
{
QLibraryStore *data = qt_library_data;
if (!data)
return;
// find any libraries that are still loaded but have a no one attached to them
LibraryMap::Iterator it = data->libraryMap.begin();
for (; it != data->libraryMap.end(); ++it) {
QLibraryPrivate *lib = it.value();
if (lib->libraryRefCount.load() == 1) {
if (lib->libraryUnloadCount.load() > 0) {
Q_ASSERT(lib->pHnd);
lib->libraryUnloadCount.store(1);
#ifdef __GLIBC__
// glibc has a bug in unloading from global destructors
// see https://bugzilla.novell.com/show_bug.cgi?id=622977
// and http://sourceware.org/bugzilla/show_bug.cgi?id=11941
lib->unload(QLibraryPrivate::NoUnloadSys);
#else
lib->unload();
#endif
}
delete lib;
it.value() = 0;
}
}
if (qt_debug_component()) {
// dump all objects that remain 在调试模式下,如果有泄露的库,则一一显示
foreach (QLibraryPrivate *lib, data->libraryMap) {
if (lib)
qDebug() << "On QtCore unload," << lib->fileName << "was leaked, with"
<< lib->libraryRefCount.load() << "users";
}
}
delete data;
}