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.服务类,纯虚类,提供接口 1.3.实现插件类,实现纯虚函数 1.4.激活插件,加入ctk框架的生命周期中 1.5.添加资源文件 1.6..pro文件 2.使用此插件 3.总结 1.生成插件 1.1.环境说明 编译ct…...

深入理解C代码中的条件编译
引言 条件编译是 C 编程中的一个重要特性,它允许开发人员根据不同的条件选择性地编译源代码的不同部分。这一特性对于编写跨平台的程序、优化代码性能或控制编译时资源消耗等方面非常重要。本文将深入探讨条件编译的工作原理、使用场景、高级应用以及注意事项&…...
Ubuntu16.04操作系统-内核优化
1. 概述 本文所用优化是生产环境中经过长期验证的内核优化策略,针对的服务器与POD主要用于高CPU、高内存、高IO的业务场景。 备注: OS: ubuntu16.04, 内核: 4.15.0-147-generic 主要涵盖以下内容优化: ulimit优化加强tcp参数其他内存参数 …...

Qt/C++编写的Onvif调试助手调试神器工具/支持云台控制/预置位设置等/有手机版本
一、功能特点 广播搜索设备,支持IPC和NVR,依次返回。可选择不同的网卡IP进行对应网段设备的搜索。依次获取Onvif地址、Media地址、Profile文件、Rtsp地址。可对指定的Profile获取视频流Rtsp地址,比如主码流地址、子码流地址。可对每个设备设…...

【原创】java+swing+mysql密码管理器系统设计与实现
个人主页:程序员杨工 个人简介:从事软件开发多年,前后端均有涉猎,具有丰富的开发经验 博客内容:全栈开发,分享Java、Python、Php、小程序、前后端、数据库经验和实战 文末有本人名片,希望和大家…...

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

iLogtail 开源两周年:社区使用调查报告
作者:玄飏 iLogtail 作为阿里云开源的可观测数据采集器,以其高效、灵活和可扩展的特性,在可观测采集、处理与分析领域受到了广泛的关注与应用。在 iLogtail 两周年之际,我们对 iLogtail 开源社区进行了一次使用调研,旨…...
Ubuntu 比较两个文件夹
比较两个文件夹下的大量文件是否一致,可以通过以下几种方式完成: 1. 使用 diff 命令 diff 命令不仅可以比较文件,还能递归比较文件夹。可以使用 -r 选项来递归比较两个目录下的文件: diff -r /path/to/dir1 /path/to/dir2 如…...

两数之和--力扣1
两数之和 题目思路C代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们…...
vue原理分析(三)new()创建Vue实例
今天我们来分析Vue实例的创建 代码如下: Vue.config.productionTip falsenew Vue({render: h > h(App),}).$mount(#app) Vue.config.productionTip false 这个配置成false,是阻止启动生产消息 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,找到 s 中最长的 回文子串。 对于该题使用中心扩展法在某些情况下可以比动态规划方法更优,尤其是在处理较长字符串时。这是因为中心扩展法具有更好的空间复杂度,并且在实际应用中可能具有更快的运行速度…...
海康威视 嵌入式 面经 海康威视嵌入式软件 嵌入式硬件总结面试经验 面试题目汇总
标题海康威视 嵌入式 面经 海康威视嵌入式软件 嵌入式硬件总结面试经验 面试题目汇总 整理总结了海康威视嵌入式的面试题目!,可以供大家面试参考 标题海康威视 嵌入式 面经 五月底投递,六月初面试,一场技术面,一场H…...
使用图论技巧——有遍数限制的最短路
给定一个 n个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你求出从 11 号点到 n 号点的最多经过 k 条边的最短距离,如果无法从 1 号点走到 n 号点,输出 impossible。 注意:图中可能 存在负权回路…...

flume 使用 exec 采集容器日志,转储磁盘
flume 使用 exec 采集容器日志,转储磁盘 在该场景下,docker 服务为superset,flume 的sources 选择 exec , sinks选择 file roll 。 任务配置 具体配置文件如下: #simple.conf: A single-node Flume configuration#…...
459重复的子字符串
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 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】实现截图功能 【需求】 实现:实现点击截图按钮,实现对页面/组件的截图 【步骤】 编写页面UI Entry Component struct Screenshot {BuildergetSnapContent() {Column() {Image().width(100%).objectFit(ImageFit.Auto).borderRadi…...

小皮面板webman ai项目本地启动教程
1.前置条件 下载小皮面板 下载后,双击安装,一路next(下一步),无需更改配置。 2.安装必须软件 在小皮面板的软件管理页,安装编号①②③④下面四个软件。 3.启动本地服务 进入到小皮面板的首页&#x…...
从零实现诗词GPT大模型:实现多头自注意力
专栏规划: https://qibin.blog.csdn.net/article/details/137728228 在上一篇文章的最后,我们已经介绍了为什么要使用多头注意力了,本篇文章我们主要来实现多头自注意力,然后综合我们之前实现的FFN和TransformerBlock其实就差不多完成了整个GPT模型的实现了。 在开始实现之…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...