Importance of the QLibraryPrivate class: several classes that can load libraries or plug-ins in Qt: & #160; & #160; & #160; & #160; QLibrary, & #160; & #160; & #160; QPluginLoader, & #160; & #160; & #160; QFactoryLoader, & #160; & #160; & #160
<<<
QLibraryPrivate class
QLibraryPrivate class importance
The following classes can be used to load libraries or plug-ins in Qt:
QLibrary,
QPluginLoader,
QFactoryLoader,
QStaticPlugin (do not study this currently)
QLibrary and QPluginLoader depend on the 'private data class' which are both QLibraryPrivate. each QLibrary or QPluginLoader object has a QLibraryPrivate object corresponding to a library or plug-in;
QFactoryLoader depends on the 'private data class' QFactoryLoaderPrivate, but the QFactoryLoaderPrivate class contains a QLibraryPrivate list, which contains multiple
Elements of the QLibraryPrivate type, corresponding to a series of libraries or plug-ins;
Therefore, QLibraryPrivate is the core data Class related to libraries or plug-ins in Qt. each database corresponds to a QLibraryPrivate object.
Important members of the QLibraryPrivate class are as follows:
Class QLibraryPrivate {public: # ifdef Q_ OS _WIN HINSTANCE # else void * # endif pHnd; // handle of the database. When the library is loaded successfully, it is set to a valid value; otherwise, it is Null QString fileName, qualifiedFileName; // library file name QString fullVersion; bool load (); // load the library, internally, the system-related function load_sys () is used to implement bool loadPlugin (); // loads and resolves instance // internally, load is called, then set the instance function bool unload (UnloadFlag flag = UnloadSys); // unload the library, internally implement void release () through the system-related function unload_sys (); // release the library, the releaseLibrary () method QFunctionPointer resolve (const ch) of QLibraryStore is called internally. Ar *); // instantiate the symbols in the library. internally, static QLibraryPrivate * findOrCreate (const QString & fileName, const QString & version = QString (), QLibrary: LoadHints loadHints = 0 );... qtPluginInstanceFunction instance; // instance is a function that generates a plug-in instance and returns QObject *. This function is initialized to NULL in the constructor. // Insert a sentence in the plug-in library file compiled in Qt (xxx. so), with "nm xxx. the so-D command lists the symbols. // you can see the qt_plugin_instance and qt_plugin_query_metadata symbols, these two symbols // are generated after the Q_PLUGIN_METADATA macro is expanded by the MOC system during the compilation of the Qt plug-in. They are two functions. // The qt_plugin_instance function loads load () in the plug-in () after successful, assign the value to the instance of the QLibraryPrivate class (this step is implemented in the loadPlugin () function). // you can directly use QLibraryPrivate: instance () the plug-in instance is accessed. // Another function, qt_plugin_query_metadata, is used to obtain the metaData of the plug-in. metaData QPointer
Inst; // plug-in instance. this inst is set only when the QLibraryPrivate object belongs to a QPluginLoader object, see the lines of code inserted below. In addition, in The unload function, inst will be deleted/* QObject * QPluginLoader: instance () {if (! IsLoaded ()&&! Load () return 0; if (! D-> inst & d-> instance) d-> inst = d-> instance (); // Set inst return d-> inst. data ();} */QJsonObject metaData; // metaData of the library... QLibrary: LoadHints loadHints; // load policy void updatePluginState (); // update the agent status of the library. the following member variable pluginState bool isPlugin () is set internally (); // check whether the library is a plug-in. the member variable pluginState static inline QJsonDocument fromRawMetaData (const char * raw) is read internally {// Obtain QJson from binary data. The metadata of the plug-in/library comes from 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 (); // Construct and analyze void mergeLoadHints (QLibrary: LoadHints loadHints); // Set the loading policy bool load_sys (); // system-related loading, detaching, or resolve functions. The system API bool unload_sys (); QFunctionPointer resolve_sys (const char *) is called internally *); /// counts how many QLibrary or QPluginLoader are attached to us, plus 1 if it's loaded QAtomicInt libraryRefCount; // reference count // counts how many times load () or loadPlugin () were called QAtomicIn T libraryUnloadCount; // load count. Although the variable name indicates the uninstall count, it can be seen from the comments that the enum {IsAPlugin, IsNotAPlugin, MightBeAPlugin} pluginState is loaded. // Mark whether the library is a plug-in, the initialization in the constructor is MightBeAPlugin, which is an uncertain state. Friend class QLibraryStore ;};
The Constructor/destructor is defined as follows. The canonicalFileName parameter in the constructor is the library's standard file name, version is the version number, and loadHints is used to control library loading.
For example, when loading the database, all the symbols in the database are instantiated (ResolveAllSymbolsHint) instead of waiting for resolve to be called.
The constructor only checks whether the library file name is valid and does not do anything in the destructor. The findOrCreate function is a static function that returns a QLibraryPrivate pointer.
The findOrCreate functions of the QLibraryStore class are consistent (This article introduces the QLibraryStore class and its findOrCreate function)
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(){}
In the QLibraryPrivate class, a member variable that requires special attention is metaData and its type is QJsonObject. it describes a series
Meta information related to the library. meta information includes important information such as the library or Qt plug-in, the keyword Keys, and so on. The meta-information-related content is described separately in another article.
<<<
QLibraryStore
First, let's look at the definition of the QLibraryStore class.
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(){}
Note: This class does not have much dry goods, and all its methods are static! There is only one non-static entity member libraryMap.
LibraryMap is a ing table of the QMap type. it stores the ing from a QString list to a QLibraryPrivate * list. The QString list contains the file names of all databases, while
In the QLibraryPrivate list, QLibraryPrivate objects corresponding to all databases are displayed. Apart from this list, the QLibraryStore class does not have any other
Entity member. In a Qt application or process, only one such ing table is needed. Therefore, only one QLibraryStore instance is required.
This can be seen from the QLibrary. cpp file (the specific definitions of the methods of the QLibraryStore class are basically in the QLibrary. cpp file ):
First, the file contains the following global static variables:
static QLibraryStore *qt_library_data = 0; static bool qt_library_data_once;
Qt_library_data is a pointer to a static global instance of the QLibraryStore class. Externally, it calls the static
Method instance () to access it. The variable qt_library_data_once is used to mark whether qt_library_data has been created.
This method is defined as follows:
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; attributes = true;} return qt_library_data;} QLibraryStore ::~ QLibraryStore () {qt_library_data = 0; // The destructor of this class only clears a global pointer, which also reflects that this class is prepared for the dedicated Global Static variable qt_library_data}
Note: Although qt_library_data is initialized to NULL, qt_library_data becomes a valid pointer when the instance method of the QLibraryStore class is called by the external system for the first time.
The findOrCreate method is used to find the library with fileName in the ing table of QLibraryStore. If yes, the corresponding QLibraryPrivate object of the library is directly returned,
If the ing table does not exist, a new QLibraryPrivate object is added to the ing table. Using this function to obtain the QLibraryPrivate object ensures that no multiple objects will appear.
QLibraryPrivate objects are mapped to the same library file.
Inline QLibraryPrivate * QLibraryStore: findOrCreate (const QString & fileName, const QString & version, QLibrary: LoadHints loadHints) {QMutexLocker (& activities); 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 (); // add 1 return lib to the reference count of the database ;}
The function opposite to findOrCreate is releaseLibrary, which is responsible for releasing a library. However, this function does not necessarily release the specified database. Instead, it first reduces the reference count of the database by 1 and is released only when the reference count is changed to 0.
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; // The destructor of QLibraryPrivate does nothing}
The cleanup function of the QLibraryStore class is used to unload (unload) all databases that are no longer in use, and release all QLibraryPrivate objects in the ing table.
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 in debug mode, if there is a leaked Library, then foreach (QLibraryPrivate * lib, data-> libraryMap) {if (lib) qDebug () <"On QtCore unload, "<lib-> fileName <" was leaked, with "<lib-> libraryRefCount. load () <"users" ;}} delete data ;}