CTK Plugin Framework中的MANIFEST.MF文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyy626562203/article/details/82781879

CTK Plugin Framework中的MANIFEST.MF文件

简述

在创建CTK插件时,MANIFEST.MF是一个必须的文件 。这个文件有特殊的格式要求。

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

清单头

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]1234567

注意: version中不能有空格

激活策略

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

激活策略的值包括:

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

依赖的插件

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

扫描二维码关注公众号,回复: 3361309 查看本文章

指令值包括:

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

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

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

头属性 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)"12

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

获取清单头

我们为插件提供了一个 MANIFEST.MF 文件:

Plugin-SymbolicName: test.plugin
Plugin-ActivationPolicy: eager
Plugin-Category: test
Plugin-ContactAddress: https://test.com/test
Plugin-Description: A plugin for test 
Plugin-Name: test_plugin
Plugin-Vendor: test
Plugin-Version: 1.0.0

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

QT += core
QT -= gui

TEMPLATE = app
CONFIG += console
TARGET = GetMetaData

LIBS += -L$$PWD/Libs -lCTKCore -lCTKPluginFramework

INCLUDEPATH += \
    $$PWD/../../CTK-master/Libs/Core \
    $$PWD/../../CTK-master/Libs/PluginFramework

SOURCES += \
    main.cpp123456789101112131415

再来看看 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/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:" << test<< "\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()

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/82781879
今日推荐