CTK 中的 MANIFEST.MF 文件

来源:互联网 发布:高考作文书推荐 知乎 编辑:程序博客网 时间:2024/06/05 05:57

简述

在创建 CTK 插件时,有一个很重要的文件 - MANIFEST.MF。这个文件究竟有什么用?有没有特殊的格式要求?

如果将 MANIFEST 翻译为中文,是“清单”的意思。在 CTK 中,MANIFEST.MF 文件包含了各种清单头(例如:Plugin-Name),用于描述插件的相关信息。

  • 简述
  • 清单头
    • 版本号
    • 激活策略
    • 依赖的插件
  • 获取清单头

版权所有:一去丶二三里,转载请注明出处:http://blog.csdn.net/liang19890820

清单头

CTK 本身提供了一些清单头,在 ctkPluginConstants 类中可以找到:

  • Plugin-SymbolicName:插件的符号名
  • Plugin-Copyright:插件的版权信息
  • Plugin-Description:插件的简要描述
  • Plugin-Name:插件的名称
  • Plugin-Vendor:插件的供应商
  • Plugin-Localization:标识插件的 Qt .qm 文件的基本名称
  • Require-Plugin:插件所需的其他插件的符号名称
  • Plugin-Version:插件的版本号
  • Plugin-ActivationPolicy:插件的激活策略
  • Plugin-UpdateLocation:在插件更新操作期间,获取新插件版本的位置

其中,大部分清单头是一些描述性字符串,比较简单。但有一些相对复杂的,它们有自己的约束,下面主要对这部分进行讲解。

版本号

插件的版本号由 Plugin-Version 头指定,语法如下:

version ::= majorVersion('.'minorVersion('.'microVersion('.'qualifier)?)?)?majorVersion ::= digit+minorVersion ::= digit+microVersion ::= digit+qualifier ::= (alpha|digit|'_'|'-')+digit ::= [0..9]alpha ::= [a..zA..Z]

注意: version 中不能有空格

激活策略

插件的激活策略由 Plugin-ActivationPolicy 头指定,默认值是 lazy

激活策略的值包括:

  • eager:插件使用 ctkPlugin::START_ACTIVATION_POLICY 选项启动,当框架启动时会立即激活。
  • lazy:插件使用 ctkPlugin::START_ACTIVATION_POLICY 选项启动,并在 ctkPlugin::STARTING 状态等待,直到插件的第一类实例化发生。插件将在实例返回给请求者之前被激活。

依赖的插件

头指令 resolution:标识 Require-Plugin 头中的解析类型,默认值是 mandatory

指令值包括:

  • optional(可选的):表示所需的插件是可选的,并且即使所需的插件没有被解析,该插件也可以被解析。
  • mandatory(强制的):表示在解析插件时,所需的插件也必须被解析。如果所需的插件不能被解析,则模块解析失败。

指令值被编码在 Require-Plugin 头中,例如:

Require-Plugin: com.acme.module.test; resolution:="optional"

头属性 plugin-version:标识 Require-Plugin 头中指定插件的一系列版本,默认值是 0.0.0

属性值被编码在 Require-Plugin 头中,例如:

Require-Plugin: com.acme.module.test; plugin-version="1.1"Require-Plugin: com.acme.module.test; plugin-version="[1.0,2.0)"

plugin-version 的属性值使用 , 来指定插件版本的范围。如果指定为单个版本,则意味着包含大于或等于指定版本的任何插件版本范围。

获取清单头

在 创建 CTK 插件(qmake) 中,我们为插件提供了一个 MANIFEST.MF 文件:

Plugin-SymbolicName: auth.pluginPlugin-ActivationPolicy: eagerPlugin-Category: testPlugin-ContactAddress: https://github.com/WaleonPlugin-Description: A plugin for authenticationPlugin-Name: auth_pluginPlugin-Vendor: WaleonPlugin-Version: 1.0.0

那么,该如何获取其中的数据呢?

这里写图片描述

创建一个 Qt 控制台应用程序,.pro 内容如下:

QT += coreQT -= guiTEMPLATE = appCONFIG += consoleTARGET = GetMetaDataLIBS += -L$$PWD/Libs -lCTKCore -lCTKPluginFrameworkINCLUDEPATH += \    $$PWD/../../CTK-master/Libs/Core \    $$PWD/../../CTK-master/Libs/PluginFrameworkSOURCES += \    main.cpp

需要同时包含 CTKCoreCTKPluginFramework

再来看看 main.cpp

#include <QCoreApplication>#include <QDirIterator>#include <QtDebug>#include <ctkPluginFrameworkFactory.h>#include <ctkPluginFramework.h>#include <ctkPluginException.h>#include <ctkPluginContext.h>const QString c_strSearchPath = "E:/CTK-Examples/GetMetaData/Plugins";int main(int argc, char *argv[]){    QCoreApplication app(argc, argv);    ctkPluginFrameworkFactory frameWorkFactory;    QSharedPointer<ctkPluginFramework> framework = frameWorkFactory.getFramework();    try {        // 初始化并启动插件框架        framework->init();        framework->start();        qDebug() << "CTK Plugin Framework start ..." << "\r\n";    } catch (const ctkPluginException &e) {        qDebug() << "Failed to initialize the plugin framework: " << e.what();        return -1;    }    // 获取插件上下文    ctkPluginContext* pluginContext = framework->getPluginContext();    // 遍历路径下的所有插件    QDirIterator itPlugin(c_strSearchPath, QStringList() << "*.dll", QDir::Files);    while (itPlugin.hasNext()) {        QString strPlugin = itPlugin.next();        try {            QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(QFileInfo(strPlugin).absoluteFilePath()));            plugin->start(ctkPlugin::START_TRANSIENT);            // 获取清单头和值            QHash<QString, QString> headers = plugin->getHeaders();            qDebug() << "headers:" << headers << "\r\n";            // 获取符号名            QString symb = plugin->getSymbolicName();            qDebug() << "symbolic name:" << symb << "\r\n";            // 获取版本号            ctkVersion version = plugin->getVersion();            qDebug() << "version:" << version.toString()                     << "major:" << version.getMajor()                     << "micro:" << version.getMicro()                     << "minor:" << version.getMinor()                     << "qualifier:" << version.getQualifier();        } catch(const ctkPluginException &e) {            qDebug() << "Failed to install plugin" << e.what();            return -1;        }    }    return app.exec();}

在 CTK 框架初始化并启动之后,我们使用 QDirIterator 遍历指定目录中的所有插件(示例中只有一个),并利用 ctkPluginContext 对每个插件进行安装。安装的每个插件都有一个相关的 ctkPlugin 对象,它是插件生命周期的接入点。

有了 ctkPlugin,一切都会变得十分简单。getHeaders() 会返回一个 QHash<QString, QString>,其中包含了所有的清单头和对应的值。如果要获取插件的符号名、版本号,除了使用 QHash 外,ctkPlugin 还提供了两个方便的函数 - getSymbolicName()getVersion()

原创粉丝点击