CTK Plugin Framework插件框架学习2--创建插件

一、前言

CTK保姆级编译教程:https://blog.csdn.net/Mr_robot_strange/article/details/128547331?spm=1001.2014.3001.5501


二、工程搭建

2.1、新建Qt工程

Qt 新建【子目录项目】,项目命名为为CTK_PluginFramework

在这里插入图片描述

然后继续新建子项目【Application】,作为主项目,项目结构如下图所示:

在这里插入图片描述


2.2、CTK环境配置

1、将CTK编译生成的CTK文件夹复制到工程目录下,例如:

在这里插入图片描述


2、将源码文件夹下的 CTK-master/Libs/PluginFramework 文件夹复制到刚刚复制的CTK文件夹下,例如:

在这里插入图片描述


3、在CTK文件夹下新建CTK_dependency.pri,并添加如下内容:

# CTK 安装路径
CTK_INSTALL_PATH = $$PWD/../CTK

# CTK 相关库所在路径(例如:CTKCore.CTKPluginFramework.lib)
CTK_LIB_PATH = $$CTK_INSTALL_PATH/lib/ctk-0.1

# CTK 相关头文件所在路径(例如:ctkPluginFramework.h)
CTK_INCLUDE_PATH = $$CTK_INSTALL_PATH/include/ctk-0.1

# CTK 插件相关头文件所在路径(主要因为用掉了service相关东西)
CTK_INCLUDE_FRAMEWORK_PATH = $$PWD/PluginFramework

# 相关库文件(CTKCore.lib、CTKWidgets.lib)
LIBS += -L$$CTK_LIB_PATH -lCTKCore -lCTKPluginFramework

INCLUDEPATH += $$CTK_INCLUDE_PATH \
               $$CTK_INCLUDE_FRAMEWORK_PATH


4、在Application.pro中导入CTK_dependency.pri

在这里插入图片描述


三、CTK Plugin Framework使用

3.1、主函数启动插件框架

main.cpp

#include "mainwindow.h"

#include <QApplication>

#include "ctkPluginFrameworkFactory.h"
#include "ctkPluginFramework.h"
#include "ctkPluginException.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    a.setApplicationName("CTK_PluginFramework");//给框架创建名称,Linux下没有会报错
    ctkPluginFrameworkFactory frameWorkFactory;
    QSharedPointer<ctkPluginFramework> framework = frameWorkFactory.getFramework();
    try {
        // 初始化并启动插件框架
        framework->init();
        framework->start();
        qDebug() << "CTK Plugin Framework start ...";
    } catch (const ctkPluginException &e) {
        qDebug() << "Failed to initialize the plugin framework: " << e.what();
        qDebug() << e.message() << e.getType();
    }

    MainWindow w;
    w.show();

    return a.exec();
}

  • QSharedPointer<ctkPluginFramework> framework:这个对象既可以作为对象,也可以作为对象指针,但要作为插件框架使用必须要用指针方法调用,所以代码里用“->”

在这里插入图片描述

注意:如果吧CTK初始化、插件安装启动、获取等操作封装成一个类,则需要把CTK相关的变量定义成类属性,不能是局部变量,否则会出现各种问题,例如获取不了服务、服务引用为空等;


3.2、插件的创建


CTK框架由一个一个可分离的插件组成,框架对插件识别有一定要求;

  • ctk插件都有自己的注册器Activator,继承自QObject和ctkPluginActivator的一个类,并实现ctkPluginActivator的start、stop函数;
  • ctk插件必须有一个资源文件(名字无所谓),前缀必须是【TARGET/META-INF】,即插【插件名/META_INF】;
  • ctk插件有一个元数据文件,名字固定为【MANIFEST.MF】,需要将其导入资源文件【TARGET/META-INF】中;

1、创建插件子项目,命名为【HelloCTK】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2、HelloCTK.pro中添加如下内容

QT += core
QT -= gui

TEMPLATE = lib
CONFIG += plugin
TARGET = HelloCTK
DESTDIR = $$OUT_PWD/bin/plugins

include($$PWD/../CTK/CTK_dependency.pri)

注意:生成的插件名(TARGET)不要有下划线,因为CTK会默认将插件名中的下划线替换为点号,最后就导致找不到插件

在这里插入图片描述


3、新建C++类HelloActivator(注册器)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

修改HelloActivator代码如下:

#ifndef HELLOACTIVATOR_H
#define HELLOACTIVATOR_H

#include <QObject>
#include "ctkPluginActivator.h"

class HelloActivator : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "HELLO_CTK")
    //向Qt的插件框架声明,希望将xxx插件放入到框架中。

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);
};

#endif // HELLOACTIVATOR_H

#include "hello_activator.h"
#include <QDebug>

void HelloActivator::start(ctkPluginContext* context)
{
    qDebug() << "HelloCTK start";
}

void HelloActivator::stop(ctkPluginContext* context)
{
    qDebug() << "HelloCTK stop";
    Q_UNUSED(context)
    //Q_UNUSED,如果一个函数的有些参数没有用到、某些变量只声明不使用,但是又不想编译器、编辑器报警报,其他没有什么实际性作用
}


4、新建资源文件qrc

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:Plugin-SymbolicName要满足这里的前缀是:TARGET/META-INF格式。TARGET的名字最好和工程名一致,不然可能出现device not open错误。

在HelloCTK文件夹中新建MANIFEST.MF文件,并加入如下内容:

插件加载后会寻找【同名前缀/META-INF】,所以前缀格式固定,可直接在MF文件里添加自己特有的元数据

Plugin-SymbolicName:HelloCTK
Plugin-Version:1.0.0
Plugin-Number:100 #元数据

在这里插入图片描述

MANIFEST.MF文件加入资源文件中

在这里插入图片描述

MANIFEST.MF文件包含ctk插件的基本信息,只要ctk框架正常识别到文件中Plugin-SymbolicName等信息,则判定它是一个ctk插件,能够正常调用activator中的start、stop函数。

MANIFEST.MF拷贝到插件生成路径下:

在这里插入图片描述

在HelloCTK.pro中添加代码:

file.path = $$DESTDIR
file.files = MANIFEST.MF
INSTALLS += file

在这里插入图片描述


3.3、插件的使用

右键HelloCTK–>【执行qmake】–>【构建“HelloCTK”】
在这里插入图片描述
在这里插入图片描述

检查生成了HelloCTK.dll

在这里插入图片描述

修改main.cpp

#include "mainwindow.h"

#include <QApplication>

#include "ctkPluginFrameworkFactory.h"
#include "ctkPluginFramework.h"
#include "ctkPluginException.h"
#include "ctkPluginContext.h"
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName("CTK_PluginFramework");//给框架创建名称,Linux下没有会报错

    ctkPluginFrameworkFactory frameworkFactory;
    QSharedPointer<ctkPluginFramework> framework = frameworkFactory.getFramework();

    // 初始化并启动插件框架
    try {
        framework->init();
        framework->start();
        qDebug() << "CTK plugin framework start...";
    } catch (const ctkPluginException &e) {
        qDebug() << "CTK plugin framework init err: " << e.what();
        return -1;
    }

    // 获取插件服务的contex
    ctkPluginContext* pluginContext = framework->getPluginContext();
    try {
        // 安装插件
        QString HelloCTK_dir = "C:/Qt_Pro/build-CTK_PluginFramework-CMake-Debug/HelloCTK/bin/plugins/HelloCTK.dll";
        QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(HelloCTK_dir));
        qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());
        // 启动插件
        plugin->start(ctkPlugin::START_TRANSIENT);
        qDebug() << "Plugin start...";
    } catch (const ctkPluginException &e) {
        qDebug() << QString("Failed install or run plugin: ") << e.what();
        return -2;
    }

    MainWindow w;
    w.show();

    return a.exec();
}

运行,成功调用HelloCTK中start内打印输出,则表明ctk插件接口正常定义并能成功加载。

其中start(ctkPlugin::START_TRANSIENT)表示立即启用插件,不设置参数的话加载后也不会立即打印输出。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值