{ "FirstName": "John", # FirstName是变量(字段)的名称;John是变量的值 "LastName": "Doe", "Age": 43, "Address": { "Street": "Downing Street 10", "City": "London", "Country": "Great Britain" }, "Phone numbers": [ "+44 1234567", "+44 2345678" ] }
#include <qpa/qplatforminputcontextplugin_p.h> #include <QtCore/QStringList> #include "QtMinimalInputMethodFrame.h" QT_BEGIN_NAMESPACE class QtMinimalInputMethodFramePlugin : public QPlatformInputContextPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformInputContextFactoryInterface" FILE "qtminimal.json") // 指定了IID和.json文件 public: QtMinimalInputMethodFrame *create(const QString &, const QStringList &); }; QtMinimalInputMethodFrame *QtMinimalInputMethodFramePlugin::create(const QString &system, const QStringList ¶mList) { Q_UNUSED(paramList); if (system.compare(system, QStringLiteral("qtminimal"), Qt::CaseInsensitive) == 0) return new QtMinimalInputMethodFrame; return 0; } QT_END_NAMESPACE #include "main.moc"
{ "Keys": [ "qtminimal" ] }
... ... static const unsigned char qt_pluginMetaData[] = { 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ', // "QTMETADATA",这段字符串可看做Qt的插件元信息的头,通过这个关键字能搜索到元信息的位置 0x71, 0x62, 0x6a, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x1b, 0x03, 0x00, 0x00, 0x03, 0x00, 0x49, 0x49, 0x44, 0x00, 0x00, 0x00, 0x37, 0x00, 0x6f, 0x72, 0x67, 0x2e, 0x71, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x51, 0x74, 0x2e, 0x51, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x46, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, 0x9b, 0x0c, 0x00, 0x00, 0x09, 0x00, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x1f, 0x00, 0x51, 0x74, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x5a, 0x60, 0xa0, 0x00, 0x07, 0x00, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x05, 0x00, 0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x95, 0x16, 0x00, 0x00, 0x08, 0x00, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x61, 0x74, 0x61, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00, 0x04, 0x00, 0x4b, 0x65, 0x79, 0x73, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x71, 0x74, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x00, 0x8b, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 }; ... ... // 留意一下QT_MOC_EXPORT_PLUGIN这个宏 QT_MOC_EXPORT_PLUGIN(QtMinimalInputMethodFramePlugin, QtMinimalInputMethodFramePlugin) ... ...
QTMETADATA qbjs^A^@^@^@^@^A^@^@^K^@^@^@ì^@^@^@^[^C^@^@^C^@ IID^@^@^@7^@org.qt-project.Qt.QPlatformInputContextFactoryInterface // IDD ^@^@^@<9b>^L^@^@^@ className^@^_^@QtMinimalInputMethodFramePlugin // 类名 ^@^@^@Z` ^@^G^@ version^@^@^@^Q^@^@^@^E^@ // 版本 debug^@<95>^V^@^@^H^@ // debug MetaData^@^@8^@^@^@^C^@^@^@4^@^@^@^T^C^@^@^D^@ // MetaData Keys^@^@^\^@^@^@^B^@^@^@^X^@^@^@^@qtminimal // Keys ^@<8b>^A^@^@^L^@^@^@^L^@^@^@¤^@^@^@T^@^@^@<98>^@^@^@<88>^@^@^@
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \ // 这个宏用于返回一个类名是IMPLEMENTATION的类的静态实例 { static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; if (!_instance) _instance = new IMPLEMENTATION; return _instance; } #if defined(QT_STATICPLUGIN) // 这部分是静态编译时用的宏,我们暂不管它 # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() Q_PLUGIN_INSTANCE(PLUGINCLASS) static const char *qt_plugin_query_metadata_##PLUGINCLASSNAME() { return (const char *)qt_pluginMetaData; } const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; return plugin; } #else // 这部分才是动态编译时用的宏 # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) Q_EXTERN_C Q_DECL_EXPORT const char *qt_plugin_query_metadata() \ // 这个函数返回一个指针,指向元信息数组 { return (const char *)qt_pluginMetaData; } Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ 这个函数返回插件类PLUGINCLASS的一个静态实例 Q_PLUGIN_INSTANCE(PLUGINCLASS) #endif
bool QLibraryPrivate::isPlugin() { if (pluginState == MightBeAPlugin) // pluginState在构造函数中会被初始化为MightBeAPlugin updatePluginState(); return pluginState == IsAPlugin; }
void QLibraryPrivate::updatePluginState() { errorString.clear(); if (pluginState != MightBeAPlugin) return; // 如果pluginState的状态已经确定了,则直接返回 bool success = false; #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) if (fileName.endsWith(QLatin1String(".debug"))) { // refuse to load a file that ends in .debug // these are the debug symbols from the libraries // the problem is that they are valid shared library files // and dlopen is known to crash while opening them // pretend we didn't see the file errorString = QLibrary::tr("The shared library was not found."); pluginState = IsNotAPlugin; return; } #endif // 这里开始设置 metaData 。findPatternUnloaded() 和 qt_get_metadata() 两个函数的内部都会设置 metaData if (!pHnd) { // 如果库还没有被加载,(pHnd==NULL说明库未被加载),则调用findPatternUnloaded函数,它内部会 // 讲对应的库文件打开,读取其内容,在其中寻找Qt的插件元信息的头Header(就是前面提到的"QTMETADATA"), // 如果找到了,就解析元信息。这种方法的好处是在不加载库的情况下也能获得其元信息。 // scan for the plugin metadata without loading success = findPatternUnloaded(fileName, this); } else { // 如果库已被加载,则调用qt_get_metadata获得元信息。 // QtPluginQueryVerificationDataFunction是一个函数指针类型,其具体类型是 : char*(*)(), 它返回 // 一个字符指针(指向一个二进制数组),准确的说,他应该返回上面提到的qt_pluginMetaData数组的指针 。 // library is already loaded (probably via QLibrary) // simply get the target function and call it. QtPluginQueryVerificationDataFunction getMetaData = NULL; getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata"); // 上面这行将库中的qt_plugin_query_metadata符号resolve出来 success = qt_get_metadata(getMetaData, this); } if (!success) { // 如果获取 元信息 失败,即当前库没有元信息,就将pluginState设置为IsNotAPlugin,代表非Qt插件。 // 这里因为当前库没有元信息,就认为它不是Qt插件,所以这是不是意味着,只有Qt插件才有元信息而普通库是没有的? if (errorString.isEmpty()){ if (fileName.isEmpty()) errorString = QLibrary::tr("The shared library was not found."); else errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName); } pluginState = IsNotAPlugin; return; } pluginState = IsNotAPlugin; // be pessimistic // 如果获取 元信息 成功,再看版本号是否符合要求,如果版本号合适,则将pluginState设置为IsAPlugin,代表是Qt插件 uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble(); bool debug = metaData.value(QLatin1String("debug")).toBool(); if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) { if (qt_debug_component()) { qWarning("In %s:\n" " Plugin uses incompatible Qt library (%d.%d.%d) [%s]", (const char*) QFile::encodeName(fileName), (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff, debug ? "debug" : "release"); } errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]") .arg(fileName) .arg((qt_version&0xff0000) >> 16) .arg((qt_version&0xff00) >> 8) .arg(qt_version&0xff) .arg(debug ? QLatin1String("debug") : QLatin1String("release")); #ifndef QT_NO_DEBUG_PLUGIN_CHECK } else if(debug != QLIBRARY_AS_DEBUG) { //don't issue a qWarning since we will hopefully find a non-debug? --Sam errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library." " (Cannot mix debug and release libraries.)").arg(fileName); #endif } else { pluginState = IsAPlugin; } }
原文地址:http://blog.csdn.net/newthinker_wei/article/details/41292011