CTK 插件之间通信
一、类通信
1、事件发布类
.h文件
#ifndef BLOGMANAGER_H #define BLOGMANAGER_H #include "ctkPluginContext.h" typedef struct Blog_Info{ QString title; QString author; QString content; } Blog; class BlogManager { public: BlogManager(ctkPluginContext *context); void publishBlog(const Blog &blog); private: ctkPluginContext *m_pContext; }; #endif // BLOGMANAGER_H
.cpp
#include "blogmanager.h" #include <service/event/ctkEventAdmin.h> #include <QtDebug> BlogManager::BlogManager(ctkPluginContext *context): m_pContext(context) { } void BlogManager::publishBlog(const Blog &blog) { qDebug() << "asdf"; ctkServiceReference ref = m_pContext->getServiceReference<ctkEventAdmin>(); if(ref) { qDebug() << "asafegdbgdf"; ctkEventAdmin *eventAdmin = m_pContext->getService<ctkEventAdmin>(ref); ctkDictionary props; props["title"] = blog.title; props["author"] = blog.author; props["content"] = blog.content; ctkEvent event("org/commontk/bloggenerator/published", props); qDebug() << "Publisher sends a message, properties:" << props; eventAdmin->sendEvent(event); } }
.h文件 激活类
#ifndef ACTIVATOR_H #define ACTIVATOR_H #include <QObject> #include "ctkPluginActivator.h" #include "ctkPluginContext.h" #include "blogmanager.h" class Activator : public QObject,public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) Q_PLUGIN_METADATA(IID "activator") public: Activator(); void start(ctkPluginContext *context); void stop(ctkPluginContext *context); private: BlogManager *m_blog; }; #endif // ACTIVATOR_H
.cpp文件
#include "activator.h" #include <QDebug> Activator::Activator() { } void Activator::start(ctkPluginContext *context) { qDebug() << "Plugin"; m_blog = new BlogManager(context); Blog blog; blog.title = "honghuang"; blog.author = "czw"; blog.content = "jilurensheng"; m_blog->publishBlog(blog); qDebug() << "xxx"; } void Activator::stop(ctkPluginContext *context) { Q_UNUSED(context) delete m_blog; }
.pro文件
QT += core QT -= gui TARGET = SendClass TEMPLATE = lib CONFIG += plugin # ctk源码路径 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/Libs/Core \ += C:/Users/ch-pc/Desktop/CTK-master/Libs/PluginFramework # ctk安装路径,主要用到的头文件等 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/PluginFramework INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/Core # ctk动态库路径 LIBS += -LC:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/bin/Debug -lCTKCore -lCTKPluginFramework # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 HEADERS += \ blogmanager.h \ activator.h SOURCES += \ blogmanager.cpp \ activator.cpp RESOURCES += \ pro.qrc
2、接收事件类
.h文件 接收事件
#ifndef BLOGEVENTHANDLE_H #define BLOGEVENTHANDLE_H #include <QObject> #include <service/event/ctkEventHandler.h> class BlogEventHandle : public QObject,public ctkEventHandler { Q_OBJECT Q_INTERFACES(ctkEventHandler) public: BlogEventHandle(); void handleEvent(const ctkEvent& event) Q_DECL_OVERRIDE; }; #endif // BLOGEVENTHANDLE_H
.cpp文件
#include "blogeventhandle.h" BlogEventHandle::BlogEventHandle() { } void BlogEventHandle::handleEvent(const ctkEvent &event) { QString title = event.getProperty("title").toString(); QString content = event.getProperty("content").toString(); QString author = event.getProperty("author").toString(); qDebug() << "EventHandler received the message, topic:" << event.getTopic() << "properties:" << "title:" << title << "content:" << content << "author:" << author; }
.h文件 激活类
#ifndef ACTIVATOR_H #define ACTIVATOR_H #include <QObject> #include "ctkPluginActivator.h" #include "ctkPluginContext.h" #include "blogeventhandle.h" class Activator : public QObject,public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) Q_PLUGIN_METADATA(IID "recv") public: Activator(); void start(ctkPluginContext *context); void stop(ctkPluginContext *context); private: BlogEventHandle *m_log; }; #endif // ACTIVATOR_H
.cpp文件
#include "activator.h" #include <QtDebug> #include <service/event/ctkEventConstants.h> Activator::Activator() { } void Activator::start(ctkPluginContext *context) { qDebug() << "recv start"; m_log = new BlogEventHandle(); ctkDictionary pros; pros[ctkEventConstants::EVENT_TOPIC] = "org/commontk/bloggenerator/published"; pros[ctkEventConstants::EVENT_FILTER] = "(author=czw)"; context->registerService<ctkEventHandler>(m_log, pros); } void Activator::stop(ctkPluginContext *context) { Q_UNUSED(context) delete m_log; }
.pro文件
QT += core QT -= gui TARGET = RecvClass TEMPLATE = lib CONFIG += plugin # ctk源码路径 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/Libs/Core \ += C:/Users/ch-pc/Desktop/CTK-master/Libs/PluginFramework # ctk安装路径,主要用到的头文件等 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/PluginFramework INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/Core # ctk动态库路径 LIBS += -LC:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/bin/Debug -lCTKCore -lCTKPluginFramework # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 HEADERS += \ blogeventhandle.h \ activator.h SOURCES += \ blogeventhandle.cpp \ activator.cpp RESOURCES += \ pro.qrc
3、在每个插件上都要加一个资源文件 前缀:/插件名/META-INF 文件:MANIFEST.MF
Plugin-SymbolicName:“插件名” Plugin-Version:1.0.0 //版本号
4、客户端
#include <QCoreApplication> #include <QtDebug> #include <ctkPluginFrameworkLauncher.h> #include <ctkPluginContext.h> #include <ctkPluginException.h> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 获取插件所在位置 QString path = QCoreApplication::applicationDirPath(); // 在插件的搜索路径列表中添加一条路径 ctkPluginFrameworkLauncher::addSearchPath(path); // 设置并启动 CTK 插件框架 ctkPluginFrameworkLauncher::start("org.commontk.eventadmin"); // 获取插件上下文 ctkPluginContext* context = ctkPluginFrameworkLauncher::getPluginContext(); // 启动插件 BlogEventHandlerUsingSlots try { // 安装插件 QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path + "/RecvClass.dll")); qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString()); plugin->start(ctkPlugin::START_TRANSIENT); qDebug() << "BlogEventHandlerUsingSlots start ..."; } catch (const ctkPluginException &e) { qDebug() << "Failed to start BlogEventHandlerUsingSlots" << e.what(); return -1; } // 启动插件 BlogManagerUsingSignals try { QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path + "/SendClass.dll")); qDebug() << QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName()).arg(plugin->getVersion().toString()); plugin->start(ctkPlugin::START_TRANSIENT); qDebug() << "BlogManagerUsingSignals start ..."; } catch (const ctkPluginException &e) { qDebug() << "Failed to start BlogManagerUsingSignals" << e.what(); return -1; } // 停止插件 ctkPluginFrameworkLauncher::stop(); return app.exec(); }
.pro文件
QT -= gui CONFIG += c++11 console CONFIG -= app_bundle # ctk源码路径 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/Libs/Core \ += C:/Users/ch-pc/Desktop/CTK-master/Libs/PluginFramework # ctk安装路径,主要用到的头文件等 INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/PluginFramework INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/Libs/Core # ctk动态库路径 LIBS += -LC:/Users/ch-pc/Desktop/CTK-master/build_MSVC2017_64/CTK-build/bin/Debug -lCTKCore -lCTKPluginFramework # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
二、信号与槽通信
1、发布事件类
#ifndef BLOGMANAGERUSINGSIGNALS_H #define BLOGMANAGERUSINGSIGNALS_H #include <QObject> #include <ctkPluginContext.h> #include <service/event/ctkEventAdmin.h> typedef struct Blog_Info{ QString title; QString author; QString content; } Blog; class BlogManagerUsingSignals : public QObject { Q_OBJECT public: BlogManagerUsingSignals(ctkPluginContext* context); void publishBlog(const Blog& blog); signals: void blogPublished(const ctkDictionary&); private: ctkPluginContext *context; }; #endif // BLOGMANAGERUSINGSIGNALS_H
.cpp文件
#include "blogmanagerusingsignals.h" BlogManagerUsingSignals::BlogManagerUsingSignals(ctkPluginContext * context) { ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>(); if(ref) { ctkEventAdmin * eventAdmin = context->getService<ctkEventAdmin>(ref); eventAdmin->publishSignal(this, SIGNAL(blogPublished(ctkDictionary)), "org/commontk/bloggenerator/published", Qt::DirectConnection); } } // 发布事件 void BlogManagerUsingSignals::publishBlog(const Blog &blog) { ctkDictionary props; props["title"] = blog.title; props["author"] = blog.author; props["content"] = blog.content; qDebug() << "Publisher sends a message, properties:" << props; emit blogPublished(props); }
.h文件
#ifndef BLOGMANAGERUSINGSIGNALSACTIVATOR_H #define BLOGMANAGERUSINGSIGNALSACTIVATOR_H #include <QObject> #include <ctkPluginActivator.h> #include <ctkPluginContext.h> #include "blogmanagerusingsignals.h" class BlogManagerUsingSignalsActivator :public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) Q_PLUGIN_METADATA(IID "signal") public: BlogManagerUsingSignalsActivator(); void start(ctkPluginContext *context); void stop(ctkPluginContext *context); private: BlogManagerUsingSignals *m_pBlog; }; #endif // BLOGMANAGERUSINGSIGNALSACTIVATOR_H
.cpp文件
#include "blogmanagerusingsignalsactivator.h" #include <QDebug> BlogManagerUsingSignalsActivator::BlogManagerUsingSignalsActivator() { } void BlogManagerUsingSignalsActivator::start(ctkPluginContext *context) { m_pBlog = new BlogManagerUsingSignals(context); Blog blog; blog.title = "CTK Event Admin"; blog.author = "czw"; blog.content = "This is a simple blog"; m_pBlog->publishBlog(blog); } void BlogManagerUsingSignalsActivator::stop(ctkPluginContext *context) { Q_UNUSED(context) delete m_pBlog; }
2、接收事件类
.h文件
#ifndef BLOGEVENTHANDLERUSINGSLOTS_H #define BLOGEVENTHANDLERUSINGSLOTS_H #include <QObject> #include <QDebug> #include <service/event/ctkEvent.h> #include <ctkPluginContext.h> class BlogEventHandlerUsingSlots : public QObject { Q_OBJECT public: BlogEventHandlerUsingSlots(ctkPluginContext *context); public slots: void onBlogPublished(const ctkEvent& event); }; #endif // BLOGEVENTHANDLERUSINGSLOTS_H
.cpp文件
#include "blogeventhandlerusingslots.h" #include "service/event/ctkEventConstants.h" #include "service/event/ctkEventAdmin.h" BlogEventHandlerUsingSlots::BlogEventHandlerUsingSlots(ctkPluginContext *context) { ctkDictionary props; props[ctkEventConstants::EVENT_TOPIC] = "org/commontk/bloggenerator/published"; ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>(); if (ref) { ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref); eventAdmin->subscribeSlot(this,SLOT(onBlogPublished(ctkEvent)), props, Qt::DirectConnection); } } void BlogEventHandlerUsingSlots::onBlogPublished(const ctkEvent &event) { QString title = event.getProperty("title").toString(); QString content = event.getProperty("content").toString(); QString author = event.getProperty("author").toString(); qDebug() << "EventHandler received the message, topic:" <<event.getTopic()<< "properties:" << "title:" << title << "content:" << content << "author:" << author; }
.h文件 激活类
#ifndef BLOGEVENTHANDLERUSINGSLOTSACTIVATOR_H #define BLOGEVENTHANDLERUSINGSLOTSACTIVATOR_H #include <QObject> #include <ctkPluginActivator.h> #include <ctkPluginContext.h> #include "blogeventhandlerusingslots.h" class BlogEventHandlerUsingSlotsActivator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) Q_PLUGIN_METADATA(IID "slot") public: BlogEventHandlerUsingSlotsActivator(); void start(ctkPluginContext *context); void stop(ctkPluginContext *context); private: QScopedPointer<BlogEventHandlerUsingSlots> m_log; }; #endif // BLOGEVENTHANDLERUSINGSLOTSACTIVATOR_H
.cpp文件
#include "blogeventhandlerusingslotsactivator.h" #include <service/event/ctkEventConstants.h> #include <service/event/ctkEventAdmin.h> #include <QDebug> BlogEventHandlerUsingSlotsActivator::BlogEventHandlerUsingSlotsActivator() { } void BlogEventHandlerUsingSlotsActivator::start(ctkPluginContext *context) { m_log.reset(new BlogEventHandlerUsingSlots(context)); } void BlogEventHandlerUsingSlotsActivator::stop(ctkPluginContext *context) { Q_UNUSED(context) }
三、注意事项:
注意在实现插件间通信时,需要先启动接收插件的dll,然后再启动发送事件的插件的dll