您的位置:首页 > 健康 > 美食 > CTK框架(四): 插件编写

CTK框架(四): 插件编写

2024/10/6 0:36:14 来源:https://blog.csdn.net/haokan123456789/article/details/142030276  浏览:    关键词: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插件!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com