CTK插件框架学习-服务工厂(06)

CTK插件框架学习-信号槽(05)icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/137240105

一、服务工厂定义

  1. 注册插件时使用服务工厂注册,使用getService根据调用者插件资源文件内容获取在服务工厂内的对应实现
  2. 在服务工厂中可以知道是哪个插件正在调用服务工厂
  3. 懒汉模式,在需要时(通过服务工厂获取时)才创建出对象实例
  4. 可以根据需要在服务工厂内创建出多个其他插件对应需要的功能

二、服务工厂插件

IPrintfService.h

#pragma once
#include <QObject>/*
* 1、通过ctkPluginConstants::SERVICE_RANKING和ctkPluginConstants::SERVICE_ID来调用不同的插件
* 2、插件不同但是在同一个dll内
* 3、插件获取策略:
*		插件容器中id最小的服务,id为插件注册时的SERVICE_RANKING属性
*		插件容器内id相同的情况,返回pid最小的服务
* 4、插件每次调用其他插件时只会生成一个实例,不会因多次调用产生多个服务实例
*/
class IPrintfService
{
public:virtual ~IPrintfService() {}virtual void printf() = 0;
};//此宏将当前这个接口类声明为接口,后面的字符串是这个接口的唯一标识。
Q_DECLARE_INTERFACE(IPrintfService, "zr.TestServiceFactory.IPrintfService")

PrintfServiceImp1类

========================PrintfServiceImp1.h===========================
#pragma once#include "IPrintfService.h"
#include <QObject>class ctkPluginContext;
class PrintfServiceImp1 :public QObject, public IPrintfService
{Q_OBJECT//当一个类继承这个接口类,表明需要实现这个接口类Q_INTERFACES(IPrintfService)public:PrintfServiceImp1();void printf();};========================PrintfServiceImp1.cpp=========================#include "PrintfServiceImp1.h"#include <qdebug.h>PrintfServiceImp1::PrintfServiceImp1()
{
}void PrintfServiceImp1::printf()
{qDebug() << "ServiceImp1 printf zr.A";
}

PrintfServiceImp2类

=============================PrintfServiceImp2.h================================
#pragma once
#include "IPrintfService.h"
#include <QObject>class ctkPluginContext;
class PrintfServiceImp2 :public QObject, public IPrintfService
{Q_OBJECT//当一个类继承这个接口类,表明需要实现这个接口类Q_INTERFACES(IPrintfService)public:PrintfServiceImp2();void printf();
};=============================PrintfServiceImp2.cpp=============================#include "PrintfServiceImp2.h"#include <qdebug.h>PrintfServiceImp2::PrintfServiceImp2()
{
}void PrintfServiceImp2::printf()
{qDebug() << "ServiceImp2 printf zr.B";
}

ServiceFactory类

============================ServiceFactory.h=============================
#pragma once
#include <qobject.h>#include <ctkServiceFactory.h>
#include <ctkPluginConstants.h>
#include <ctkVersion.h>
#include "IPrintfService.h"class ServiceFactory :public QObject, public ctkServiceFactory
{Q_OBJECTQ_INTERFACES(ctkServiceFactory)public:ServiceFactory();QObject* getService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration);void ungetService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration, QObject* service);private:QObject* getServiceByName(QString name);private:int m_count;
};============================ServiceFactory.cpp===========================#include "ServiceFactory.h"#include <qdebug.h>#include "PrintfServiceImp1.h"
#include "PrintfServiceImp2.h"ServiceFactory::ServiceFactory()
{m_count = 0;
}QObject * ServiceFactory::getService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration)
{Q_UNUSED(registration)qDebug() << "getSymbolicName: " << plugin->getSymbolicName();qDebug() << "plugin count: " << m_count++;QHash<QString, QString> headers = plugin->getHeaders();//ctkVersion version = ctkVersion::parseVersion(headers.value(ctkPluginConstants::PLUGIN_VERSION));//QString name = headers.value(ctkPluginConstants::PLUGIN_NAME);//qDebug() << "PLUGIN_NAME: " << name;QString pluginName = headers.value(ctkPluginConstants::PLUGIN_NAME);QObject* obj = getServiceByName(pluginName);return obj;}void ServiceFactory::ungetService(QSharedPointer<ctkPlugin> plugin, ctkServiceRegistration registration, QObject * service)
{Q_UNUSED(plugin)Q_UNUSED(registration)Q_UNUSED(service)qDebug() << "getSymbolicName: " << plugin->getSymbolicName();QHash<QString, QString> headers = plugin->getHeaders();
}QObject * ServiceFactory::getServiceByName(QString name)
{if (name.contains("zr.A")){return new PrintfServiceImp1();}else{return new PrintfServiceImp2();}
}

PluginActivator类

=============================PluginActivator.h================================
#pragma once
#include <qobject.h>
#include "ctkPluginActivator.h"
#include "ctkPluginContext.h"
#include "PrintfServiceImp1.h"
#include "PrintfServiceImp2.h"class PluginActivator :public QObject, ctkPluginActivator
{Q_OBJECTQ_INTERFACES(ctkPluginActivator)//向Qt的插件框架声明,希望将xxx插件放入到框架中。Q_PLUGIN_METADATA(IID "TestServiceFactory")//向qt框架申明插件(qt5版本)public:PluginActivator();void start(ctkPluginContext *context);void stop(ctkPluginContext *context);
private:};=============================PluginActivator.cpp==============================#include "PluginActivator.h"
#include <QDebug>
#include "ctkPluginContext.h"
#include "ctkPluginFrameworkLauncher.h"#include "ServiceFactory.h"
#include "IPrintfService.h"PluginActivator::PluginActivator()
{}
void PluginActivator::start(ctkPluginContext *context)
{ServiceFactory* serviceFactory = new ServiceFactory();context->registerService<IPrintfService>(serviceFactory);}void PluginActivator::stop(ctkPluginContext *context)
{Q_UNUSED(context);}

三、测试插件

新建插件可以参考CTK插件框架学习-新建插件(02)

1、在新插件中调用服务工厂

	//使用服务工厂ctkServiceReference ref = context->getServiceReference<IPrintfService>();if (ref){IPrintfService* service = qobject_cast<IPrintfService*>(context->getService(ref));if (service != nullptr){service->printf();}}

 2、新插件MANIFEST.MF文件内容如下:

Plugin-SymbolicName:TestUseServiceFactoryPluginA
Plugin-Version: 1.0.0//版本号添加多级或带字母会导致插件加载失败
Plugin-Name: zr.A键值对类型可以参考ctkPluginConstants.h文件,根据服务工厂内使用的字段类型进行修改,
如在服务工厂内以获取插件名称的方式区分不同插件,则定义(Plugin-Name: zr.A),
然后通过以下方式获取属性值进行区分
QHash<QString, QString> headers = plugin->getHeaders();
QString pluginName = headers.value(ctkPluginConstants::PLUGIN_NAME);

四、加载插件

#include "CTKPlugin.h"
#include <QtWidgets/QApplication>#include <iostream>
#include <QStyleFactory>
#include <QDir>
#include <QDirIterator>
#include <QDebug>
#include "ctkPluginFrameworkFactory.h"
#include "ctkPluginFramework.h"
#include "ctkPluginException.h"
#include "ctkPluginContext.h"
#include "ctkPluginFrameworkLauncher.h"
#include "../TestServiceFactory/IPrintfService.h"
/*
* 1、注意:Plugin-SymbolicName要满足这里的前缀是:TARGET/META-INF格式。TARGET的名字最好和工程名一致,不然可能出现device not open错误。
* 2、如果CTK初始化、插件安装启动等是在一个类中,则与CTK相关的变量应定义成类的属性,不能是成员变量,否则获取不到服务
* 3、CTK插件组成:
(1)每个插件有自己的注册器Activator,继承自QObject和ctkPluginActivator的一个类,并实现ctkPluginActivator的start、stop函数
(2)每个插件必须有一个资源文件,名称一般与插件名称一致,前缀必须为TARGET/META-INF,例:插件名称/META-INF
(3)每个插件必须添加一个元数据文件,名字必须为MANIFEST.MF,并添加到资源文件中
* 4、QSharedPointer framework这个对象既可以作为对象也可以作为对象指针,但要作为插件框架使用必须要用指针方法调用
* 5、生成的插件名(TARGET)不要有下划线,因为CTK会默认将插件名中的下划线替换成点号,最后导致找不到插件 
*/
int main(int argc, char *argv[])
{QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QApplication a(argc, argv);a.setApplicationName("ctktest");//Linux下没有名称报错QString path = QCoreApplication::applicationDirPath();//启用通信插件框架
#ifdef _DEBUGctkPluginFrameworkLauncher::addSearchPath(path + "/CTKPlugins");//ctkPluginFrameworkLauncher::addSearchPath("E:/Demo(Qt5)/08_CTKPlugin/CTKPlugin/CTK/lib/ctk-0.1/plugins");
#elsectkPluginFrameworkLauncher::addSearchPath(path + "/CTKPlugins");
#endif // _DEBUG// 设置并启动 CTK 插件框架try {ctkPluginFrameworkLauncher::start("org.commontk.eventadmin");}catch (ctkException e){std::cout << e.message().toStdString() << std::endl;}// 启动插件工厂ctkPluginFrameworkFactory* ctkFrameWorkFactory = new ctkPluginFrameworkFactory;QSharedPointer<ctkPluginFramework> framework = ctkFrameWorkFactory->getFramework();try {framework->init();framework->start();}catch (const ctkPluginException& e){std::cout << "framework init fail" << std::endl;}//QString dir = QCoreApplication::applicationDirPath();//dir += "/plugins/TestPlugin.dll";//QUrl url = QUrl::fromLocalFile(dir);QSharedPointer<ctkPlugin> plugin;
#if 1QDirIterator iter(path + "/plugins/", { "*.dll" }, QDir::NoFilter, QDirIterator::Subdirectories);while (iter.hasNext()) {//qDebug() << iter.next();QString dllPath = iter.next();QUrl url = QUrl::fromLocalFile(dllPath);try{plugin = framework->getPluginContext()->installPlugin(url);qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());//获取MANIFEST.MF中的数据QHash<QString, QString> headers = plugin->getHeaders();ctkVersion version = ctkVersion::parseVersion(headers.value(ctkPluginConstants::PLUGIN_VERSION));QString name = headers.value(ctkPluginConstants::PLUGIN_NAME);}catch (ctkPluginException e) {std::cout << e.message().toStdString() << e.getType() << std::endl;}try {plugin->start(ctkPlugin::START_TRANSIENT);//表示立即启用插件,不设置参数的话加载后也不会立即打印输出qDebug() << QString("Plugin[%1_%2] started").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString());}catch (ctkPluginException e) {std::cout << e.message().toStdString() << e.getType() << std::endl;}}
#else#endif//在main函数中调用服务工厂获取到的getSymbolicName为"system.plugin"ctkServiceReference ref = framework->getPluginContext()->getServiceReference<IPrintfService>();if (ref){IPrintfService* service = qobject_cast<IPrintfService*>(framework->getPluginContext()->getService(ref));if (service != nullptr){service->printf();}}//ctkPlugin::State sta = plugin->getState();//ctkPluginFrameworkLauncher::stop();//plugin->stop(); //plugin->uninstall();//sta = plugin->getState();CTKPlugin c;c.show();return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/301645.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rabbitmq死信交换机,死信队列使用

背景 对于核心业务需要保证消息必须正常消费&#xff0c;就必须考虑消费失败的场景&#xff0c;rabbitmq提供了以下三种消费失败处理机制 直接reject&#xff0c;丢弃消息&#xff08;默认&#xff09;返回nack&#xff0c;消息重新入队列将失败消息投递到指定的交换机 对于核…

代码随想录第34天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 贪心算法&#xff0c;这不就是常识&#xff1f;还能叫贪心&#xff1f;LeetCode&#xff1a;1005.K次取反后最大化的数组和_哔哩哔…

10.枚举

1.背景及定义 枚举是在JDK1.5以后引入的。 主要用途是&#xff1a; 将一组常量组织起来&#xff0c; 在这之前表示一组常量通常使用定义常量的方式&#xff1a; public static final int RED 1; public static final int GREEN 2; public static final int BLACK 3; 但是…

Web Component 组件库有什么优势

前言 前端目前比较主流的框架有 react&#xff0c;vuejs&#xff0c;angular 等。 我们通常去搭建组件库的时候都是基于某一种框架去搭建&#xff0c;比如 ant-design 是基于 react 搭建的UI组件库&#xff0c;而 element-plus 则是基于 vuejs 搭建的组件库。 可能你有这种体…

C语言进阶课程学习记录-第22课 - 条件编译使用分析

C语言进阶课程学习记录-第22课 - 条件编译使用分析 条件编译基本概念条件编译实验cmd命令窗口输入演示条件编译本质实验-ifdefcmd定义宏结果比较 include本质实验-间接包含同一个头文件解决重复包含的方法-ifndef实验-条件编译的应用小结 本文学习自狄泰软件学院 唐佐林老师的 …

线上研讨会 | 新一代数字化技术赋能机器人及智能产线行业高质量发展

随着智能制造的快速推进&#xff0c;制造业转型升级到了关键阶段。越来越多的企业以数字化技术搭配智能机器人及智慧产线&#xff0c;主动实现数字化转型。达索系统3D体验平台是实现企业数字化转型的新一代数智化平台&#xff0c;基于型、数字驱动、数字化连续技术&#xff0c;…

基于Socket简单的UDP网络程序

⭐小白苦学IT的博客主页 ⭐初学者必看&#xff1a;Linux操作系统入门 ⭐代码仓库&#xff1a;Linux代码仓库 ❤关注我一起讨论和学习Linux系统 1.前言 网络编程前言 网络编程是连接数字世界的桥梁&#xff0c;它让计算机之间能够交流信息&#xff0c;为我们的生活和工作带来便利…

ICLR24_OUT-OF-DISTRIBUTION DETECTION WITH NEGATIVE PROMPTS

摘要 分布外检测&#xff08;OOD Detection&#xff09;的研究对于开放世界&#xff08;open-world&#xff09;学习非常重要。受大模型&#xff08;CLIP&#xff09;启发&#xff0c;部分工作匹配图像特征和提示来实现文本-图像特征之间的相似性。 现有工作难以处理具有与已…

牛顿:Archetype AI 的开创性模型,实时解读真实世界的新宠儿

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

免费云服务器汇总,最长永久免费使用

随着云计算技术的快速发展&#xff0c;越来越多的企业和个人开始将业务迁移到云端。云服务器作为云计算的重要组成部分&#xff0c;以其灵活、高效、可扩展等特点受到广泛关注。然而&#xff0c;许多人在初次接触云服务器时&#xff0c;可能会对高昂的价格望而却步。为了帮助大…

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

【C++学习】哈希的应用—位图与布隆过滤器

目录 1.位图1.1位图的概念1.2位图的实现3.位图的应用 2.布隆过滤器2.1 布隆过滤器提出2.2布隆过滤器概念2.3如何选择哈希函数个数和布隆过滤器长度2.4布隆过滤器的实现2.4.1布隆过滤器插入操作2.4.2布隆过滤器查找操作2.4.3 布隆过滤器删除 2.5 布隆过滤器优点2.6布隆过滤器缺陷…

[BT]BUUCTF刷题第13天(4.1)

第13天 Upload-Labs-Linux (Basic) Pass-01 根据题目提示&#xff0c;该题为绕过js验证。 一句话木马&#xff1a; <?php eval(system($_POST["cmd"]));?> // 符号 表示后面的语句即使执行错误&#xff0c;也不报错。 // eval() 把括号内的字符串全部…

lottery-攻防世界

题目 flag在这里要用钱买&#xff0c;这是个赌博网站。注册个账号&#xff0c;然后输入七位数字&#xff0c;中奖会得到相应奖励。 githacker获取网站源码 &#xff0c;但是找到了flag文件但是没用。 bp 抓包发现api.php&#xff0c;并且出现我们的输入数字。 根据题目给的附…

未来的技术发展趋势

文章目录 前言一、人工智能技术势必聚焦安全能力二、单云环境逐渐让位于多云环境三、后量子密码或将在美大范围普及总结前言 2023 年,与网络空间安全息息相关的人工智能等技术发展迅猛,新的信息安全时代已然拉开大幕。在目睹了 ChatGPT、“星链”和量子通信等技术展现出的巨…

【C语言】函数相关选择题

前言 关于函数相关的选择题。 题目一&#xff1a; C语言规定&#xff0c;在一个源程序中&#xff0c;main函数的位置&#xff08; &#xff09; A .必须在最开始 B .必须在库函数的后面 C .可以任意 D .必须在最后 题解&#xff1a;选择C。 main函数为C语言中整个工程的程序入…

STL优先队列比较器

有两个比较器&#xff0c;在std里面&#xff0c;一个是greater&#xff0c;一个是less&#xff0c;他们都有一个可以指定的模板类型。 #include <bits/stdc.h> using namespace std; struct node {bool operator ()(const string& a, const string& b){return a…

Linux集群部署项目

目录 一&#xff0c;环境准备 1.1.安装MySQL 1.2.安装JDK 1.3.安装TomCat 1.4.安装Nginx 二&#xff0c;部署 2.1.后台服务部署 2.2.Nginx配置负载均衡及静态资源部署 一&#xff0c;环境准备 1.1.安装MySQL 将MySQL的安装包上传至服务器 查看系统中是否存在mariadb&…

X86汇编速成

平时用的电脑都是X86的&#xff0c;但是现在大家都在搞RISC-V&#xff0c;计组也都开始以RISC-V作为示例&#xff0c;所以专门回头来补一下X86的汇编&#xff0c;方便平时使用。 寄存器register X86_64中一共有16个64位的通用寄存器&#xff0c;分别为&#xff1a; RAX, RBX,…

微信小程序开发——实现跳转公众号文章

小程序中要显示公众号的文章&#xff0c;该怎么做? 比如&#xff0c;下面的文章地址&#xff1a; 第一款小程序欢迎体验小程序&#xff0c;如有好的想法和建议请留言&#xff0c;不胜感激&#xff01;https://mp.weixin.qq.com/s?__bizMzI2MjQ4Mzg0NA&mid2247483669&…