当前位置: 首页 > news >正文

CTK框架(四): 插件编写

目录

1.生成插件

1.1.环境说明

1.2.服务类,纯虚类,提供接口

1.3.实现插件类,实现纯虚函数

1.4.激活插件,加入ctk框架的生命周期中

1.5.添加资源文件

1.6..pro文件

2.使用此插件

3.总结


1.生成插件

1.1.环境说明

编译ctk:Qt5.12.12+MSVC2017_64+Cmake

生成插件:Qt5.12.2+MSVC2017_64+qmake

1.2.服务类,纯虚类,提供接口

PluginAService.h

#ifndef PLUGINASERVICE_H
#define PLUGINASERVICE_H
#include <QtPlugin>class PluginAService
{
public:virtual ~PluginAService() {}virtual void A_Func() = 0;
};#define PluginAService_iid "org.commontk.service.demos.PluginAService"
Q_DECLARE_INTERFACE(PluginAService, PluginAService_iid)
//此宏将当前这个接口类声明为接口,后面的一长串就是这个接口的唯一标识。#endif // PLUGINASERVICE_H

1.3.实现插件类,实现纯虚函数

PluginAImpl.h

#ifndef PLUGINAIMPL_H
#define PLUGINAIMPL_H#include "PluginAService.h"
#include <QObject>class ctkPluginContext;class PluginAImpl : public QObject, public PluginAService
{Q_OBJECTQ_INTERFACES(PluginAService)/*此宏与Q_DECLARE_INTERFACE宏配合使用。Q_DECLARE_INTERFACE:声明一个接口类Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类*/public:PluginAImpl(ctkPluginContext* context);void A_Func() Q_DECL_OVERRIDE;
};#endif // PLUGINAIMPL_H

PluginAImpl.cpp

#include "PluginAImpl.h"
#include <QtDebug>PluginAImpl::PluginAImpl(ctkPluginContext* context)
{}void PluginAImpl::A_Func()
{qDebug() << "A_Func()";
}

1.4.激活插件,加入ctk框架的生命周期中

PluginAActivator.h

#ifndef PLUGINAACTIVATOR_H
#define PLUGINAACTIVATOR_H
#include <QObject>
#include "ctkPluginActivator.h"
#include "PluginAService.h"class PluginAActivator : public QObject, public ctkPluginActivator
{Q_OBJECTQ_INTERFACES(ctkPluginActivator)Q_PLUGIN_METADATA(IID "PLUGINA")//向Qt的插件框架声明,希望将xxx插件放入到框架中。public:void start(ctkPluginContext* context);void stop(ctkPluginContext* context);private:QSharedPointer<PluginAService> m_s;
};
#endif // PLUGINAACTIVATOR_H

PluginAActivator.cpp

#include "PluginAActivator.h"
#include "PluginAImpl.h"
#include <QDebug>void PluginAActivator::start(ctkPluginContext* context)
{PluginAImpl* pluginAImpl = new PluginAImpl(context);context->registerService<PluginAService>(pluginAImpl);m_s.reset(pluginAImpl);
}void PluginAActivator::stop(ctkPluginContext* context)
{Q_UNUSED(context)//Q_UNUSED,如果一个函数的有些参数没有用到、某些变量只声明不使用,但是又不想编译器、编辑器报警报,其他没有什么实际性作用
}

1.5.添加资源文件

资源名随便取,前缀为:PluginA/META_INF,文件名为:MANIFEST.MF

MANIFEST.MF内容:

注意:MANIFEST.MF的路径必须是这样,:/插件名/META-INF/MANIFEST.MF,否则系统找打不到此资源文件,此插件加载就会报异常。

MANIFEST.MF文件中有很多可填内容,在ctkPluginConstants.h中能找到相关宏定义

1.6..pro文件

include($$PWD/../../Plugins/Plugins.pri)QT       += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11TARGET = PluginA# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0HEADERS += \PluginAActivator.h \PluginAImpl.h \PluginAService.hSOURCES += \PluginAActivator.cpp \PluginAImpl.cppRESOURCES += \resource.qrc

2.使用此插件

main.cpp

#include <QCoreApplication>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFramework.h>
#include <ctkPluginException.h>
#include <ctkPluginContext.h>
#include <QtDebug>
#include <QUrl>
#include "PluginAService.h"QString static firstPlugin_filePath = "D:/openCode/ctkcreator/bin/qmake/debug/plugins/PluginA.dll";int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);QApplication a(argc, argv);//启动框架QString path = QCoreApplication::applicationDirPath() + "/linkplugins";ctkPluginFrameworkLauncher::addSearchPath(path, true);ctkProperties properties;properties.insert(ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN,     ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);ctkPluginFrameworkFactory fwFactory(properties);QSharedPointer<ctkPluginFramework> framework = fwFactory.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;}// 获取插件服务的contexctkPluginContext* pluginContext = framework->getPluginContext();try {// 安装插件QSharedPointer<ctkPlugin> plugin = pluginContext->installPlugin(QUrl::fromLocalFile(firstPlugin_filePath));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;}// 获取服务引用ctkServiceReference reference = pluginContext->getServiceReference<PluginAService>();if (reference) {// 获取指定 ctkServiceReference 引用的服务对象PluginAService* service = qobject_cast<PluginAService*>(pluginContext->getService(reference));if (service != Q_NULLPTR) {// 调用服务service->A_Func();}}return a.exec();
}

不出意外,在控制台会打印出"A_Func()"。

3.总结

        这就是在Qt和CTK中编写和使用插件的基本流程。CTK作为Qt的扩展,主要用于医疗应用开发,但插件的编写和加载机制仍然遵循Qt的标准做法。希望这能帮助你开始编写自己的CTK插件!

相关文章:

CTK框架(四): 插件编写

目录 1.生成插件 1.1.环境说明 1.2.服务类&#xff0c;纯虚类&#xff0c;提供接口 1.3.实现插件类&#xff0c;实现纯虚函数 1.4.激活插件&#xff0c;加入ctk框架的生命周期中 1.5.添加资源文件 1.6..pro文件 2.使用此插件 3.总结 1.生成插件 1.1.环境说明 编译ct…...

深入理解C代码中的条件编译

引言 条件编译是 C 编程中的一个重要特性&#xff0c;它允许开发人员根据不同的条件选择性地编译源代码的不同部分。这一特性对于编写跨平台的程序、优化代码性能或控制编译时资源消耗等方面非常重要。本文将深入探讨条件编译的工作原理、使用场景、高级应用以及注意事项&…...

Ubuntu16.04操作系统-内核优化

1. 概述 本文所用优化是生产环境中经过长期验证的内核优化策略&#xff0c;针对的服务器与POD主要用于高CPU、高内存、高IO的业务场景。 备注: OS: ubuntu16.04, 内核&#xff1a; 4.15.0-147-generic 主要涵盖以下内容优化&#xff1a; ulimit优化加强tcp参数其他内存参数 …...

Qt/C++编写的Onvif调试助手调试神器工具/支持云台控制/预置位设置等/有手机版本

一、功能特点 广播搜索设备&#xff0c;支持IPC和NVR&#xff0c;依次返回。可选择不同的网卡IP进行对应网段设备的搜索。依次获取Onvif地址、Media地址、Profile文件、Rtsp地址。可对指定的Profile获取视频流Rtsp地址&#xff0c;比如主码流地址、子码流地址。可对每个设备设…...

【原创】java+swing+mysql密码管理器系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 文末有本人名片&#xff0c;希望和大家…...

JavaEE-HTTPHTTPS

目录 HTTP协议 一、概念 二、http协议格式 http请求报文 http响应报文 URL格式 三、认识方法 四、认识报头 HTTP响应中的信息 HTTPS协议 对称加密 非对称加密 中间人攻击 解决中间人攻击 HTTP协议 一、概念 HTTP (全称为 "超⽂本传输协议") 是⼀种应⽤…...

iLogtail 开源两周年:社区使用调查报告

作者&#xff1a;玄飏 iLogtail 作为阿里云开源的可观测数据采集器&#xff0c;以其高效、灵活和可扩展的特性&#xff0c;在可观测采集、处理与分析领域受到了广泛的关注与应用。在 iLogtail 两周年之际&#xff0c;我们对 iLogtail 开源社区进行了一次使用调研&#xff0c;旨…...

Ubuntu 比较两个文件夹

比较两个文件夹下的大量文件是否一致&#xff0c;可以通过以下几种方式完成&#xff1a; 1. 使用 diff 命令 diff 命令不仅可以比较文件&#xff0c;还能递归比较文件夹。可以使用 -r 选项来递归比较两个目录下的文件&#xff1a; diff -r /path/to/dir1 /path/to/dir2 如…...

两数之和--力扣1

两数之和 题目思路C代码 题目 思路 根据题目要求&#xff0c;元素不能重复且不需要排序&#xff0c;我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中&#xff0c;使用目标值减去当前循环的nums[i]&#xff0c;得到差值&#xff0c;如果我们…...

vue原理分析(三)new()创建Vue实例

今天我们来分析Vue实例的创建 代码如下&#xff1a; Vue.config.productionTip falsenew Vue({render: h > h(App),}).$mount(#app) Vue.config.productionTip false 这个配置成false&#xff0c;是阻止启动生产消息 new Vue({render: h > h(App),}).$mount(#app)…...

Spring MVC: 构建Web应用的强大框架

Spring MVC: 构建现代Web应用的强大框架 1. MVC设计模式简介 MVC (Model-View-Controller) 是一种广泛使用的软件设计模式,它将应用程序的逻辑分为三个相互关联的组件: Model (模型): 负责管理数据、业务逻辑和规则。View (视图): 负责用户界面的展示,将数据呈现给用户。Con…...

网络学习-eNSP配置NAT

NAT实现内网和外网互通 #给路由器接口设置IP地址模拟实验环境 <Huawei>system-view Enter system view, return user view with CtrlZ. [Huawei]undo info-center enable Info: Information center is disabled. [Huawei]interface gigabitethernet 0/0/0 [Huawei-Gigabi…...

动态规划-最长回文子串

题目描述 给你一个字符串 s&#xff0c;找到 s 中最长的 回文子串。 对于该题使用中心扩展法在某些情况下可以比动态规划方法更优&#xff0c;尤其是在处理较长字符串时。这是因为中心扩展法具有更好的空间复杂度&#xff0c;并且在实际应用中可能具有更快的运行速度&#xf…...

海康威视 嵌入式 面经 海康威视嵌入式软件 嵌入式硬件总结面试经验 面试题目汇总

标题海康威视 嵌入式 面经 海康威视嵌入式软件 嵌入式硬件总结面试经验 面试题目汇总 整理总结了海康威视嵌入式的面试题目&#xff01;&#xff0c;可以供大家面试参考 标题海康威视 嵌入式 面经 五月底投递&#xff0c;六月初面试&#xff0c;一场技术面&#xff0c;一场H…...

使用图论技巧——有遍数限制的最短路

给定一个 n个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c; 边权可能为负数。 请你求出从 11 号点到 n 号点的最多经过 k 条边的最短距离&#xff0c;如果无法从 1 号点走到 n 号点&#xff0c;输出 impossible。 注意&#xff1a;图中可能 存在负权回路…...

flume 使用 exec 采集容器日志,转储磁盘

flume 使用 exec 采集容器日志&#xff0c;转储磁盘 在该场景下&#xff0c;docker 服务为superset&#xff0c;flume 的sources 选择 exec &#xff0c; sinks选择 file roll 。 任务配置 具体配置文件如下&#xff1a; #simple.conf: A single-node Flume configuration#…...

459重复的子字符串

给定一个非空的字符串 s &#xff0c;检查是否可以通过由它的一个子串重复多次构成。 public repeatedSubstringPattern(String s){int n s.length();for(int i 1; i < n / 2; i){if(n % i ! 0) continue;// substring获取子字符串是左闭右开的String ss s.substring(0,…...

【HarmonyOS NEXT】实现截图功能

【HarmonyOS NEXT】实现截图功能 【需求】 实现&#xff1a;实现点击截图按钮&#xff0c;实现对页面/组件的截图 【步骤】 编写页面UI Entry Component struct Screenshot {BuildergetSnapContent() {Column() {Image().width(100%).objectFit(ImageFit.Auto).borderRadi…...

小皮面板webman ai项目本地启动教程

1.前置条件 下载小皮面板 下载后&#xff0c;双击安装&#xff0c;一路next&#xff08;下一步&#xff09;&#xff0c;无需更改配置。 2.安装必须软件 在小皮面板的软件管理页&#xff0c;安装编号①②③④下面四个软件。 3.启动本地服务 进入到小皮面板的首页&#x…...

从零实现诗词GPT大模型:实现多头自注意力

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 在上一篇文章的最后,我们已经介绍了为什么要使用多头注意力了,本篇文章我们主要来实现多头自注意力,然后综合我们之前实现的FFN和TransformerBlock其实就差不多完成了整个GPT模型的实现了。 在开始实现之…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...