CTK框架使用

CTK框架使用基于Qt的CTK框架的使用QT的plugin插件的创建方式在介绍CTK框架的使用方法之前我们首先介绍一下QT的plugin插件的创建方式。QT提供两种API来创建插件:扩展Qt库本身的高级API。例如:定制databasedrivers,imageformats,textcodecs,customstyles,etc.扩展应用程序的低级API如果你像创建一个可以在QtDes

大家好,又见面了,我是你们的朋友全栈君。

基于Qt的CTK框架的使用

QT的plugin插件的创建方式

在介绍CTK框架的使用方法之前我们首先介绍一下QT的plugin插件的创建方式。

QT提供两种API来创建插件:

  1. 扩展Qt库本身的高级API。例如:定制database drivers, image formats, text codecs, custom styles, etc.
  2. 扩展应用程序的低级API
    如果你像创建一个可以在Qt Designer 下使用的插件,请查看Qt Designer module documentation 。

扩展应用程序的低级API:

不是只用Qt自己可以加载插件,Qt Application 也可以扩展插件。 qt加载插件使用QPluginLoader类来实现。

要扩展Qt Application 使用插件需要完成如下的步骤:
1. 定义一系列和插件调用的纯虚类来作为调用的接口
2. 使用 Q_DECLARE_INTERFACE() 注册接口到 元对象系统
3. 使用QpluginLoader 加载插件
4. 使用 qobject_cast() 测试该插件是否实现了该接口

要创建插件需要如下步骤:
1. 首先声明一个继承QObject和 插件接口类
2. 使用Q_INTERFACES() 注册接口到元对象系统
3. 使用Q_PLUGIN_METADATA()导出数据到元对象系统
4. 对。pro文件编译

示例代码:

class FilterInterface
{
public:
    virtual ~FilterInterface() {}

    virtual QStringList filters() const = 0;
    virtual QImage filterImage(const QString &filter, const QImage &image,
                               QWidget *parent) = 0;
};

#include <QObject>
#include <QtPlugin>
#include <QStringList>
#include <QImage>

#include <plugandpaint/interfaces.h>

class ExtraFiltersPlugin : public QObject, public FilterInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json")
    Q_INTERFACES(FilterInterface)

public:
    QStringList filters() const;
    QImage filterImage(const QString &filter, const QImage &image,
                       QWidget *parent);
};

技术原理

插件就是动态库, 插件技术是使用c++中的多态,定义抽象类接口, 然后再PLugin中实现抽象类接口。
plugin可以动态加载, 动态更新。 可以实现应用的热插拔技术。 对内存的使用效率比较高。
当要使用的时候用interface 类指针指向 Plugin 就可以使用插件中的函数了。
CTK系统可以管理这些插件, 当需要的时候就可以直接从系统中获取相应的插件。 然后用想用的抽象接口指向这个插件就可以使用了。

技术框架

插件框架采用分层, 模块化管理。CTK系统可以管理插件的生命周期, 在运行时动态加载和卸载插件从而实现软件用的热插拔。
ctk框架就像是一个仓库来存储所有的插件, 要使用的时候只需要从仓库里拿出相应的插件实例就可以。而不用关系怎么找到这个实例, 怎么管理这个实例

技术使用

项目架构分析

每一个中型或大型的项目,在实际开发之前,其代码组织架构一定会经过仔细的规划,比如:目录架构(头文件放在哪个目录;
lib库放在哪个目录;开发源代码放在哪个目录;生成的项目插件放在哪个目录;最终发布程序放在哪个目录)。
现在,假设我们要为图书馆开发一个图书管理程序,称之为:LibraryProject,然后在该文件夹下有:includes,libs,plugins,bin,application等文件夹。


其基本用途如下:applications用于放置项目加载程序的源码;bin下包含conf、plugins目录,bin下存放项目入口exe程序以及独立运行时依赖的dll文件,
bin/conf下存放项目配置文件,bin/plugins下放置项目中所有使用到自己开发的插件;includes目录用于放置头文件,包括第三方头文件以及项目中自己定义的接口文件等;
libs用于放置项目中使用的第三方开源库的lib文件;plugins用于放置项目中所有的插件开发源码;而base.pri是用来定义或加载项目中通用的内容,
比如:INCLUDEPATH在该文件中定义则在其它插件子项目中只要include一下这个文件,就可以使用includes中包含的所有头文件。

基于CTK框架的插件的编写规则

1 interface接口定义

首先是interface接口我们以后称之为service(服务) 该类是抽象类, 在c++里叫做纯虚类(如果不知到自己搜索 这里不做过多的介绍)
服务类的定义示例代码如下:

#ifndef CONTROLPLUGIN_SERVICE_H
#define CONTROLPLUGIN_SERVICE_H
#include <qobject.h>
struct ControlPlugin_Service
{
public:
    virtual ~ControlPlugin_Service(){}
    virtual void init()=0;
};
Q_DECLARE_INTERFACE(ControlPlugin_Service, "org.commontk.pluginControl")

#endif // CONTROLPLUGIN_SERVICE_H  

virtual ~ControlPlugin_Service(){}

析构函数我们定义成虚函数, 原因: 由于提供的接口只有服务类, 要使用插件的内容必须要服务类指针指向我们的实现类。
由于调用者没有我们的实现类的定义和声明所有不可能直接析构我们的实现类这样就可能造成内存泄漏, 
但是使用虚析构函数这样当析构这个服务类是就会自动析构对应的实现类的实例。

Q_DECLARE_INTERFACE(ControlPlugin_Service, "org.commontk.pluginControl")
//声明使用服务的接口和唯一id, 系统会定义一些宏函数
2服务类的实现

接下来就是我们服务类的实现了, 在这里我们必须继承QObject, 和服务类 并且声明接口Q_INTERFACE()
//h

class ControlPlugin_Plugin : public QObject, public ControlPlugin_Service
{
    Q_OBJECT
    Q_INTERFACES(ControlPlugin_Service)

public:
    ControlPlugin_Plugin(ctkPluginContext *pc);
    virtual void init();
};

#endif // CONTROLPLUGIN_PLUGIN_H

//cpp

#include "controlplugin_plugin.h"
#include <ctkPluginContext.h>

#include <QDebug>
ControlPlugin_Plugin::ControlPlugin_Plugin(ctkPluginContext *pc)
{
    pc->registerService<ControlPlugin_Service>(this);
    //把服务类注册到我们的ctk系统供我们获取该类的实现类实例
}


void ControlPlugin_Plugin::init()
{
    qDebug()<<"hello";
}
3 ctkPluginActivator (ctk的生命周期类)

接下来是最重要的类 该类必须继承ctkPluginActivator (ctk的生命周期类), 里面函数得有start(), stop(),
s是一个指向服务类的指针,该类析构后自动析构服务类。
//h

#ifndef CONTROLSHARELIB_H
#define CONTROLSHARELIB_H

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

class  ControlShareLib : public QObject, public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)

#if (QT_VERSION_MAJOR>4)
    Q_PLUGIN_METADATA(IID "ControlShareLibd")

#endif

public:
    void start(ctkPluginContext *contex);
    void stop(ctkPluginContext *context);
private:
    QScopedPointer<ControlPlugin_Service> s;
};
#endif // CONTROLSHARELIB_H

//cpp

void ControlShareLib::start(ctkPluginContext *contex)
{
    s.reset(new ControlPlugin_Plugin(contex));
}
void ControlShareLib::stop(ctkPluginContext *context)
{
    Q_UNUSED(context)
}
4内部资源文件MANIFEST.MF 对插件的描述

资源路径名必须是 $TARGET/META-INF/MANIFEST.MF

例如生成库是 libplugin.so.0.0 TARGET是plugin

MANIFEST.MF 内容示例如下:

Plugin-SymbolicName: ControlShareLib
Plugin-ActivationPolicy: eager
Plugin-Category: test
Plugin-ContactAddress: http://www.commontk.org
Plugin-Description: Test plugin for framework, ControlShareLib
Plugin-Name: ControlShareLib
Plugin-Vendor: CommonTK
Plugin-Version: 1.0.1

详细内容可以书写如下:

const QString ctkPluginConstants::SYSTEM_PLUGIN_LOCATION = "System Plugin";
const QString ctkPluginConstants::SYSTEM_PLUGIN_SYMBOLICNAME = "system.plugin";

const QString ctkPluginConstants::FRAMEWORK_VERSION = "org.commontk.pluginfw.version";
const QString ctkPluginConstants::FRAMEWORK_VENDOR = "org.commontk.pluginfw.vendor";
const QString ctkPluginConstants::FRAMEWORK_STORAGE = "org.commontk.pluginfw.storage";
const QString ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN = "org.commontk.pluginfw.storage.clean";
const QString ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT = "onFirstInit";
const QString ctkPluginConstants::FRAMEWORK_PLUGIN_LOAD_HINTS = "org.commontk.pluginfw.loadhints";
const QString ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES = "org.commontk.pluginfw.preloadlibs";

const QString ctkPluginConstants::PLUGIN_SYMBOLICNAME = "Plugin-SymbolicName";
const QString ctkPluginConstants::PLUGIN_COPYRIGHT = "Plugin-Copyright";
const QString ctkPluginConstants::PLUGIN_DESCRIPTION = "Plugin-Description";
const QString ctkPluginConstants::PLUGIN_NAME = "Plugin-Name";
const QString ctkPluginConstants::PLUGIN_VENDOR = "Plugin-Vendor";
const QString ctkPluginConstants::PLUGIN_LOCALIZATION = "Plugin-Localization";
const QString ctkPluginConstants::PLUGIN_LOCALIZATION_DEFAULT_BASENAME = "CTK-INF/l10n/plugin";
const QString ctkPluginConstants::REQUIRE_PLUGIN = "Require-Plugin";
const QString ctkPluginConstants::PLUGIN_VERSION_ATTRIBUTE = "plugin-version";
const QString ctkPluginConstants::PLUGIN_VERSION = "Plugin-Version";
const QString ctkPluginConstants::PLUGIN_ACTIVATIONPOLICY = "Plugin-ActivationPolicy";
const QString ctkPluginConstants::PLUGIN_UPDATELOCATION = "Plugin-UpdateLocation";

const QString ctkPluginConstants::ACTIVATION_EAGER = "eager";
const QString ctkPluginConstants::ACTIVATION_LAZY = "lazy";

const QString ctkPluginConstants::RESOLUTION_DIRECTIVE = "resolution";
const QString ctkPluginConstants::RESOLUTION_MANDATORY = "mandatory";
const QString ctkPluginConstants::RESOLUTION_OPTIONAL = "optional";


const QString ctkPluginConstants::OBJECTCLASS = "objectclass";

// ATTENTION!!! If the value is changed, change also ctkEventConstants::SERVICE_ID
const QString ctkPluginConstants::SERVICE_ID = "service.id";

// ATTENTION!!! If the value is changed, change also ctkEventConstants::SERVICE_PID
const QString ctkPluginConstants::SERVICE_PID = "service.pid";

const QString ctkPluginConstants::SERVICE_RANKING = "service.ranking";
const QString ctkPluginConstants::SERVICE_VENDOR = "service.vendor";
const QString ctkPluginConstants::SERVICE_DESCRIPTION = "service.description";
5最后附上Qt的工程文件。
#-------------------------------------------------
#
# Project created by QtCreator 2016-12-27T16:04:46
#
#-------------------------------------------------

QT       -= gui

TEMPLATE = lib                          //生成目标为库
CONFIG += c++11                         //支持c++11
DEFINES += CONTROLSHARELIB_LIBRARY
DESTDIR = $$PWD/../../bin/plugins     //生成插件的存放路径
SOURCES += controlsharelib.cpp \
    controlplugin_plugin.cpp

HEADERS += controlsharelib.h\
    controlplugin_plugin.h \
    controlplugin_service.h

unix {
    target.path = /usr/lib
    INSTALLS += target
}

INCLUDEPATH += $$PWD/../../include/ctkH 	//需要用到的头文件路径
	LIBS += -L$$PWD/../../bin  -lCTKCore  -lCTKPluginFramework \ //需要用到库文件路径

RESOURCES += \
    controlsharelib.qrc

ctkPluginContext 详解

类作用:ctkPluginContext 是一个在框架内部的插件执行上下文。 该上下文可以存取其它插件的方法, 实现插件间的通信。

内部方法作用如下:

  1. 通过框架发送事件。
  2. 用框架服务注册服务类。
  3. 从框架注册服务中检索服务引用 (ServiceReferences)
  4. 获取和释放一个参考的引用
  5. 安装插件到服务
  6. 获取框架中更新的插件列表
  7. 获取一个插件 ctkPlugin 类
  8. 通过框架为plugin创建一个flile存储在数据库里
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134936.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • htc u11第三方rom_htc手机windows系统

    htc u11第三方rom_htc手机windows系统小弟写得差请勿拍砖,如果有意见请直接回复本贴!谢谢!技术有限,部分可能不详细或者错误的请各位指出,大家交流!前言:一个完整的ROM根目录会有以下几个文件夹及文件:dataMETA-INsystemboot.img系统目录说明1.应用程序安装目录1)系统应用程序所在目录/system/app/*.apk2)用户安装应用程序所在目录/

    2022年10月15日
  • iptables

    iptables

  • eclipse自动提示+自动补全[通俗易懂]

    eclipse自动提示+自动补全[通俗易懂]解决代码的自动提示问题:1、打开Eclipse->Window->Perferences2、找到Java下的 Editor下的 ContentAssist, 右边出现的选项中,有一个AutoactivationtriggersforJava:会看到只有一个”.”存在。表示:只有输入”.”之后才会有代码提示3、先把上图中”.”的地方输入几个随便的字

  • SSTI完全学习[通俗易懂]

    一、什么是SSTISSTI就是服务器端模板注入(Server-SideTemplateInjection),也给出了一个注入的概念。常见的注入有:SQL注入,XSS注入,XPATH注入,XML注入,代码注入,命令注入等等。sql注入已经出世很多年了,对于sql注入的概念和原理很多人应该是相当清楚了,SSTI也是注入类的漏洞,其成因其实是可以类比于sql注入的。sql注入是从用户获…

  • https加密原理(转)

    https加密原理(转)HTTP、HTTPS在我们日常开发中是经常会接触到的。我们也都知道,一般Android应用开发,在请求API网络接口的时候,很多使用的都是HTTP协议;使用浏览器打开网页,也是利用HTTP协议。看来HTTP真是使用广泛啊,但是,HTTP是不安全的。利用网络抓包工具就可以知道传输中的内容,一览无余。比如我经常会使用Fiddler来抓包,搜集一些有趣的API接口。那么…

  • Jmeter监控服务器性能「建议收藏」

    Jmeter监控服务器性能「建议收藏」JMeter是一款压力测试工具,我们也可以用它来监控服务器资源使用情况。JMeter正常自带可以通过Tomcat的/manager/status来监控服务资源使用情况。这种情况只能监控Tomcat支持的资源使用部分。本文主要来说一下如何通过JMeter插件来监控服务器CPU、内存、磁盘、网络等相关资源。JMeter插件网址:http://jmeter-plugins.org/Perf

    2022年10月19日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号