| 
                             
                              | 
                                   
                                    | 编辑推荐: |   
                                    | 本文首先怼项目进行了介绍,接下来就是介绍了如下几个案例打印插件编写、日志插件编写、界面类等相关内容。 文章来自于csdn,由火龙果Anna编辑推荐。
 |  |  一、项目介绍 1、主要为了在此小型测试项目中用到几乎所有ctk的常用知识: 插件间通信、服务工厂、服务追踪、事件监听、框架封装 2、项目共包含3个插件 
                            日志插件:用于模拟将接收的信息存储到日志中【这里只做简单的打印】,并且能够接收信息【主要来自界面插件】 打印插件:根据不同的插件返回提供不同打印服务 界面插件:封装一个界面插件,能够向框架发送信息【类方式和信号槽方式】 3、架构图 
    二、打印插件编写 1、工程结构 
 2、接口类 absprintserver.h 
                             
                              | #ifndef ABSPRINTSERVER_H #define ABSPRINTSERVER_H
 #include <QObject>class AbsPrintServer
 {
 public:
 virtual ~AbsPrintServer(){}
 virtual void print(QString) = 0;
 };
 Q_DECLARE_INTERFACE (AbsPrintServer, "judesmorning.zxy.AbsPrintServer")
 #endif // ABSPRINTSERVER_H |  
                            3、实现类1,为日志插件提供服务 printserver.h 
                             
                              | #ifndef PRINTSERVER_H #define PRINTSERVER_H
 #include <QObject>
 #include "absprintserver.h"
 class PrintServer : public QObject, public 
                                  AbsPrintServer{
 Q_OBJECT
 Q_INTERFACES(AbsPrintServer)
 public:
 PrintServer();
 void print(QString info) override;
 };
 #endif // PRINTSERVER_H |   printserver.cpp 
                             
                              | #include "printserver.h" #include <QDebug>
 PrintServer::PrintServer()
 {
 } void PrintServer::print(QString info){
 qDebug()<<info+"----print plugin 
                                  for FirstPlugin";
 }
 |  
                            4、实现类2,为界面插件提供服务 printservert.h 
                             
                              | #ifndef PRINTSERVERT_H #define PRINTSERVERT_H
 #include <QObject>
 #include "absprintserver.h"
 class PrintServerT : public QObject, public 
                                  AbsPrintServer{
 Q_OBJECT
 Q_INTERFACES(AbsPrintServer)
 public:
 PrintServerT();
 void print(QString info) override;
 };
 #endif // PRINTSERVERT_H |   printservert.cpp 
                             
                              | #include "printservert.h" #include <QDebug>
 #include <QTime>
 PrintServerT::PrintServerT()
 {
 }void PrintServerT::print(QString info)
 {
 qDebug()<<QTime:: currentTime().toString ("HH:mm:ss 
                                  ")<<info+" ----print plugin for 
                                  CreateCtkUiPlugin";
 }
 |  
                            5、实现类3,为其他插件提供服务  printserverd.h 
                             
                              | #ifndef PRINTSERVERD_H #define PRINTSERVERD_H
 #include <QObject>
 #include "absprintserver.h"
 class PrintServerD : public QObject, public 
                                  AbsPrintServer{
 Q_OBJECT
 Q_INTERFACES(AbsPrintServer)
 public:
 PrintServerD();
 void print(QString info) override;
 };
 #endif // PRINTSERVERD_H |   printserverd.cpp 
                             
                              | #include "printserverd.h" #include <QDebug>
 PrintServerD::PrintServerD()
 {
 } void PrintServerD::print(QString info){
 qDebug()<<info+"....----print plugin 
                                  for unknown plugin";;
 }
 |  
                            6、单独为接口编写服务追踪类 tracker.h 
                             
                              | #ifndef TRACKER_H #define TRACKER_H
 #include "ctkServiceTracker.h"#include "absprintserver.h"
 #include "ctkPluginContext.h"
 class Tracker : public ctkServiceTracker<AbsPrintServer*>
 {
 public:
 Tracker(ctkPluginContext* context);
 protected:
 AbsPrintServer* addingService (const ctkServiceReference& 
                                  reference) override;
 void modifiedService (const ctkServiceReference& 
                                  reference,  AbsPrintServer* service) override;
 void removedService (const ctkServiceReference& 
                                  reference,  AbsPrintServer* service) override;
 private:
 ctkPluginContext* context;
 };
 #endif // TRACKER_H |   tracker.cpp 
                             
                              | #include "tracker.h" Tracker::Tracker(ctkPluginContext *context)
 : ctkServiceTracker<AbsPrintServer*> (context)
 {
 } AbsPrintServer *Tracker::addingService (const 
                                  ctkServiceReference &reference){
 AbsPrintServer* service = static_cast<AbsPrintServer*> 
                                  (ctkServiceTracker::addingService(reference));
 return service;
 }
 void Tracker::modifiedService (const ctkServiceReference 
                                   &reference, AbsPrintServer* service){
 ctkServiceTracker::modifiedService (reference,service);
 }
 void Tracker::removedService (const ctkServiceReference 
                                   &reference, AbsPrintServer* service){
 ctkServiceTracker:: removedService (reference,service);
 }
 |  
                            注意这个服务追踪类是在日志插件里使用的,只是从职责上来讲这个类应该编写此插件的人来编写,降低耦合性 三、日志插件编写 1、工程结构 
 2、接口类 abslogservice.h 
                             
                              | #include "tracker.h" Tracker::Tracker(ctkPluginContext *context)
 : ctkServiceTracker<AbsPrintServer*> (context)
 {
 } AbsPrintServer *Tracker::addingService (const 
                                  ctkServiceReference &reference){
 AbsPrintServer* service = static_cast<AbsPrintServer*> 
                                  (ctkServiceTracker::addingService(reference));
 return service;
 }
 void Tracker::modifiedService (const ctkServiceReference 
                                  &reference, AbsPrintServer* service){
 ctkServiceTracker::modifiedService (reference,service);
 }
 void Tracker::removedService (const ctkServiceReference 
                                  &reference, AbsPrintServer* service){
 ctkServiceTracker:: removedService (reference,service);
 }
 |  
                            3、实现类 logservice.h 
                             
                              | #ifndef LOGSERVICE_H #define LOGSERVICE_H
 #include <QObject>
 #include "includes.h"
 #include "abslogservice.h"
 #include "service/event/ctkEventHandler.h"
 #include "ctkPluginFrameworkEvent.h"
 #include "ctkPluginEvent.h"
 #include "ctkServiceEvent.h"
 #include "tracker.h"
 class ctkPluginContext;class LogService : public QObject, public AbsLogService, 
                                  public ctkEventHandler
 {
 Q_OBJECT
 Q_INTERFACES(AbsLogService)
 Q_INTERFACES(ctkEventHandler)
 public:
 LogService(ctkPluginContext* context);
 void log(QString info) override;
 void handleEvent(const ctkEvent& event) 
                                  override;
 private slots:
 // 监听框架事件
 void onFrameworkEvent(const ctkPluginFrameworkEvent& 
                                  event);
 // 监听插件事件
 void onPluginEvent(const ctkPluginEvent& 
                                  event);
 // 监听服务事件
 void onServiceEvent(const ctkServiceEvent& 
                                  event);
 private:
 QString getLevelStr(const _Log_Level& level) 
                                  const;//获取日志类型字符串
 void print(QString info);//使用打印插件打印东西
 private:
 ctkPluginContext* context;
 QScopedPointer<Tracker> p_tracker;
 };
 #endif // LOGSERVICE_H |  logservice.cpp 
                             
                              | #include "logservice.h" #include <QTime>
 #include <QDebug>
 #include "ctkPluginContext.h"
 #include "absprintserver.h"
 #include "ctkServiceTracker.h"
 LogService::LogService(ctkPluginContext* context):context(context)
 {
 #if 1 //通过服务追踪方式获取打印插件
 p_tracker.reset(new Tracker(context));
 p_tracker->open();
 // AbsPrintServer* printService = static_cast 
                                  <AbsPrintServer*>(p_tracker->getService());
 // printService- >print ("use tracker 
                                  to get print  plugin--------log plugin");
 #endif
 #if 1 //监听ctk事件context->connectFrameworkListener(this, SLOT(onFrameworkEvent(ctkPluginFrameworkEvent)));
 context->connectPluginListener (this, SLOT 
                                  (onPluginEvent(ctkPluginEvent)));
 //QString filter = QString("(%1=%2)").arg(ctkPluginConstants: 
                                  :OBJECTCLASS).arg ("org.commontk.eventadmin");// 
                                  过滤 ctkEventAdmin 服务
 //context->connectServiceListener (this,SLOT 
                                  (onServiceEvent(ctkServiceEvent))); //, filter);
 context->connectServiceListener (this,"onServiceEvent"); 
                                  //, filter);
 #endif
 }
 void LogService::log(QString info){
 qDebug()<<"log plugin save a log 
                                  --- >"+ QTime::currentTime().toString 
                                  ("HH:mm:ss ") + info;
 }
 void LogService::handleEvent(const ctkEvent 
                                  &event){
 qDebug()<<"log plugin rcv a event 
                                  ----------log plugin";
 _Log_Level level = static_cast<_Log_Level> 
                                  (event.getProperty("level").toInt());
 QString pluginName = event.getProperty ("pluginName").toString();
 QString info =  event.getProperty("info").toString();
 QString rcvLogInfo = QString("%1 %2 %3.")
 .arg(getLevelStr(level))
 .arg(pluginName)
 .arg(info);
 log(rcvLogInfo);
 }
 QString LogService::getLevelStr (const _Log_Level 
                                  &level) const{
 QString ret;
 switch (static_cast<int>(level))
 {
 case LOG_LEVEL_DEBUG:
 ret = "DEBUG";
 break;
 case LOG_LEVEL_INFO:
 ret = "INFO";
 break;
 case LOG_LEVEL_WARNING:
 ret = "WARNING";
 break;
 case LOG_LEVEL_ERROR:
 ret = "ERROR";
 break;
 case LOG_LEVEL_CRITICAL:
 ret = "CRITICAL";
 break;
 default:
 ret = "UKNOWN";
 break;
 }
 return ret;
 }
 void LogService::print(QString info){
 #if 0 //直接向ctk框架索要服务
 ctkServiceReference reference = context-> 
                                   getServiceReference<AbsPrintServer>();
 if (reference)
 {
 // 获取指定 ctkServiceReference 引用的服务对象
 AbsPrintServer* service =  qobject_cast<AbsPrintServer*> 
                                  (context->getService(reference));
 if (service != Q_NULLPTR)
 {
 // 调用服务
 service->print(info);
 }
 }
 #endif
 #if 1 //通过tracker向ctk索要服务AbsPrintServer* service =  static_cast<AbsPrintServer*> (p_tracker->getService());
 if (service != Q_NULLPTR)
 {
 service->print("log plugin with tracker:"+info);
 }
 else
 {
 qDebug()<<"get AbsPrintServer from 
                                  tracker failed";
 }
 #endif
 }
 void LogService:: onFrameworkEvent (const ctkPluginFrameworkEvent 
                                  &event){
 if (!event.isNull())
 {
 QSharedPointer<ctkPlugin> plugin = event.getPlugin();
 qDebug() << "FrameworkEvent: [" 
                                  << plugin->getSymbolicName() << 
                                  "]" << event.getType() << 
                                  event.getErrorString();
 }
 else
 {
 qDebug() << "The framework event 
                                  is null";
 }
 }
 void LogService::onPluginEvent (const ctkPluginEvent 
                                  &event){
 if (!event.isNull())
 {
 QSharedPointer<ctkPlugin> plugin = event.getPlugin();
 qDebug() << "PluginEvent:  [" 
                                  << plugin->getSymbolicName() << 
                                  "]"  << event.getType();
 }
 else
 {
 qDebug() << "The plugin event is 
                                  null";
 }
 }
 void LogService::onServiceEvent (const ctkServiceEvent 
                                  &event){
 if (!event.isNull())
 {
 ctkServiceReference ref = event.getServiceReference();
 QSharedPointer<ctkPlugin> plugin = ref.getPlugin();
 qDebug() << "ServiceEvent: [" 
                                  << plugin->getSymbolicName() << 
                                  "]"   << event.getType() << 
                                  ref.getUsingPlugins();
 }
 else
 {
 qDebug() << "The service event is 
                                  null";
 }
 }
 |  
                            4、激活类 firstpluginactivator.h 
                             
                              | #ifndef FIRSTPLUGINACTIVATOR_H #define FIRSTPLUGINACTIVATOR_H
 #include <QObject>
 #include "ctkPluginActivator.h"
 #include "ctkPluginContext.h"
 #include "logservice.h"
 class FirstPluginActivator : public QObject, 
                                  public ctkPluginActivator
 {
 Q_OBJECT
 Q_INTERFACES(ctkPluginActivator)
 Q_PLUGIN_METADATA(IID "LogPlugin")
 public:FirstPluginActivator();
 void start(ctkPluginContext *context);
 void stop(ctkPluginContext *context);
 private:
 QScopedPointer<AbsLogService> m_log;
 };
 #endif // FIRSTPLUGINACTIVATOR_H |   firstpluginactivator.cpp 
                             
                              | #ifndef FIRSTPLUGINACTIVATOR_H #define FIRSTPLUGINACTIVATOR_H
 #include <QObject>
 #include "ctkPluginActivator.h"
 #include "ctkPluginContext.h"
 #include "logservice.h"
 class FirstPluginActivator :  public QObject, 
                                  public ctkPluginActivator
 {
 Q_OBJECT
 Q_INTERFACES(ctkPluginActivator)
 Q_PLUGIN_METADATA(IID "LogPlugin")
 public:FirstPluginActivator();
 void start(ctkPluginContext *context);
 void stop(ctkPluginContext *context);
 private:
 QScopedPointer<AbsLogService> m_log;
 };
 #endif // FIRSTPLUGINACTIVATOR_H |  firstpluginactivator.cpp 
                             
                              | #include "firstpluginactivator.h"#include <QDebug>
 #include "service/event/ctkEventHandler.h"
 #include "service/event/ctkEventConstants.h"
 #include "absprintserver.h"
 FirstPluginActivator:: FirstPluginActivator()
 {
 } //注册插件并订阅事件void FirstPluginActivator::start (ctkPluginContext 
                                  *context)
 {
 // qDebug() << " FirstPluginActivator 
                                  start";
 LogService* service = new LogService(context);
 m_log.reset(service);
 ctkDictionary props;
 props [ctkEventConstants::EVENT_TOPIC] =  "kdhy/yunwei/generalevent/log";
 props [ctkEventConstants::EVENT_FILTER] =  "(pluginName=CreateCtkUiPlugin)";
 context->registerService <ctkEventHandler>(service, 
                                  props);
 context->registerService <AbsLogService>(service);
 }
 void FirstPluginActivator::stop (ctkPluginContext 
                                  *context){
 Q_UNUSED(context)
 }
 |  
                            5、插件间通信的结构体定义 includes.h 
                             
                              | #ifndef 
                                  INCLUDES_H#define INCLUDES_H
 #include <QString>/*公共定义*/
 //日志相关enum _Log_Level{
 LOG_LEVEL_DEBUG = 0,
 LOG_LEVEL_INFO,
 LOG_LEVEL_WARNING,
 LOG_LEVEL_ERROR,
 LOG_LEVEL_CRITICAL
 };//日志等级
 typedef struct _LogInfo {
 _Log_Level level; //日志类型
 QString pluginName; //插件名称
 QString info; //日志信息
 } LogInfo;//日志详情
 #endif // INCLUDES_H
 |  四、界面类 1、工程结构 
 2、接口类 absuiservice.h 
                             
                              | #ifndef ABSUISERVICE_H #define ABSUISERVICE_H
 #include <QObject>
 class AbsUiService{
 public:
 virtual ~AbsUiService(){}
 virtual void init() = 0;
 };
 Q_DECLARE_INTERFACE (AbsUiService,"judesmorning.zxy.AbsUiService")
 #endif // ABSUISERVICE_H
 |  3、实现类 uiservice.h 
                             
                              | #ifndef UISERVICE_H #define UISERVICE_H
 #include <QObject>#include "absuiservice.h"
 #include "includes.h"
 #include "myui.h"
 class ctkPluginContext;class UiService : public QObject, public AbsUiService
 {
 Q_OBJECT
 Q_INTERFACES(AbsUiService)
 public:
 UiService(ctkPluginContext* context);
 void init() override;
 private slots:
 void publishLogEventSlot(LogInfo logInfo);
 private:
 ctkPluginContext* context;//ctk上下文对象
 Myui myui;//界面对象
 };
 #endif // UISERVICE_H |   uiservice.cpp 
                             
                              | #include "uiservice.h" #include "ctkPluginContext.h"
 #include "service/event/ctkEventAdmin.h"
 #include <QDebug>
 #include <QDialog>
 UiService::UiService(ctkPluginContext* context):context(context)
 {
 context->registerService<AbsUiService>(this);
 QObject::connect(&myui,SIGNAL (publishLogEventSignal 
                                  (LogInfo)), this,SLOT(publishLogEventSlot (LogInfo)));
  //发送日志事件到ctk框架,signal方式ctkServiceReference ref = context->getServiceReference<ctkEventAdmin>();
 if (ref)
 {
 ctkEventAdmin* eventAdmin = context->getService<ctkEventAdmin>(ref);
 eventAdmin->publishSignal (&myui,SIGNAL 
                                  (publishLogSignal(ctkDictionary)), "kdhy/yunwei/generalevent/log",Qt 
                                  ::QueuedConnection);
 }
 }
 void UiService::init()
 {
 myui.show();
 }
 //发送日志事件到ctk框架,event方式void UiService::publishLogEventSlot(LogInfo 
                                  logInfo)
 {
 ctkServiceReference ref =  context-> getServiceReference<ctkEventAdmin>();
 if (ref) {
 ctkEventAdmin* eventAdmin =  context-> getService<ctkEventAdmin>(ref);
 ctkDictionary props;
 props["level"] = logInfo.level;
 props["pluginName"] = logInfo.pluginName;
 props["info"] = logInfo.info;
 ctkEvent event ("kdhy/yunwei/generalevent/log", 
                                  props);
 qDebug()  << "ui plugin send " 
                                  << logInfo.info;
 eventAdmin->sendEvent(event);//sendEvent:同步 
                                  postEvent:异步
 }
 }
 |  
                            4、主显示界面 myui.h 
                             
                              | #ifndef MYUI_H #define MYUI_H
 #include <QWidget>#include "includes.h"
 #include "service/event/ctkEventAdmin.h"
 namespace Ui {
 class Myui;
 }
 class Myui : public QWidget{
 Q_OBJECT
 public:explicit Myui(QWidget *parent = nullptr);
 ~Myui();
 signals:void publishLogEventSignal(LogInfo);
 void publishLogSignal(ctkDictionary info);
 private slots:void on_pushButton_clicked();
  void on_pushButton_2_clicked(); private:Ui::Myui *ui;
 };
 #endif // MYUI_H |   myui.cpp 
                             
                              | #include "myui.h" #include "ui_myui.h"
 Myui::Myui(QWidget *parent) :QWidget(parent),
 ui(new Ui::Myui)
 {
 ui->setupUi(this);
 }
 Myui::~Myui(){
 delete ui;
 }
 //发送event事件void Myui::on_pushButton_clicked()
 {
 qDebug()<<"ui plugin send a event";
 LogInfo logInfo;
 logInfo.level = LOG_LEVEL_INFO;
 logInfo.pluginName = "CreateCtkUiPlugin";
 logInfo.info =  "Event info:"+ui->textEdit->toPlainText();
 emit publishLogEventSignal(logInfo);
 }
 //发送信号事件
 void Myui::on_pushButton_2_clicked()
 {
 ctkDictionary props;
 props["level"] = LOG_LEVEL_INFO;;
 props["pluginName"] = "CreateCtkUiPlugin";
 props["info"] =  "Signal info:"+ui->textEdit->toPlainText();
 emit publishLogSignal(props);
 }
 |  
                            myui.ui 
 5、激活类 uiactivator.h 
                             
                              | #ifndef UIACTIVATOR_H #define UIACTIVATOR_H
 #include <QObject>#include "ctkPluginActivator.h"
 #include "ctkPluginContext.h"
 #include "uiservice.h"
 class UiActivator: public QObject, public ctkPluginActivator{
 Q_OBJECT
 Q_INTERFACES(ctkPluginActivator)
 Q_PLUGIN_METADATA(IID "UiPlugin")
 public:
 UiActivator();
 void start(ctkPluginContext *context);
 void stop(ctkPluginContext *context);
 private:
 QScopedPointer<AbsUiService> m_ui;
 };
 #endif // UIACTIVATOR_H |   uiactivator.cpp 
                             
                              | #include "uiactivator.h" #include <QtDebug>
 UiActivator::UiActivator()
 {
 }void UiActivator::start(ctkPluginContext *context)
 {
 // qDebug() << "ui plugin start";
 m_ui.reset(new UiService(context));
 }
 void UiActivator::stop(ctkPluginContext *context){
 Q_UNUSED(context)
 }
 |  
                            6、插件间通信的结构体定义 includes.h 
                             
                              | #ifndef INCLUDES_H #define INCLUDES_H
 #include <QString>/*公共定义*/
 //日志相关enum _Log_Level{
 LOG_LEVEL_DEBUG = 0,
 LOG_LEVEL_INFO,
 LOG_LEVEL_WARNING,
 LOG_LEVEL_ERROR,
 LOG_LEVEL_CRITICAL
 };//日志等级
 typedef struct _LogInfo {
 _Log_Level level; //日志类型
 QString pluginName; //插件名称
 QString info; //日志信息
 } LogInfo;//日志详情
 #endif // INCLUDES_H
 |  五、使用 1、新建控制台工程 
    由于用到了界面,所以这个工程不能是无界面的 2、.pro 
                             
                              | #------------------------------------------------- #
 # Project created by QtCreator 2020-07-02T18:12:37
 #
 #-------------------------------------------------
 #QT += coreQT += gui widgets
 CONFIG += console c++11
 CONFIG -= app_bundle
 TARGET = CtkFramework#TEMPLATE = app
 # The following define makes your compiler 
                                  emit warnings if you use# any feature of Qt which has been marked as 
                                  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 you use 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 \
 pullservice.cpp
 # Default rules for deployment.qnx: target.path = /tmp/$${TARGET}/bin
 else: unix:!android: target.path = /opt/$${TARGET}/bin
 !isEmpty(target.path): INSTALLS += target
 # CTK源码路径INCLUDEPATH += $$PWD/third_libs/ctk/include/CTK_src/Core 
                                  \
 += $$PWD/third_libs/ctk/include/CTK_src/PluginFramework
 # CTK安装路径
 INCLUDEPATH += $$PWD/third_libs/ctk/include/CTK_install/Core 
                                  \
 += $$PWD/third_libs/ctk/include/CTK_install/PluginFramework
 # CTK库路径
 LIBS += -L$$PWD/third_libs/ctk/libs -lCTKCore 
                                  -lCTKPluginFramework
 # 插件头文件路径
 INCLUDEPATH += $$PWD/third_libs/plugin/include
 HEADERS += \pullservice.h
 |  
                            3、框架封装类 pullservice.h 
                             
                              | #ifndef PULLSERVICE_H #define PULLSERVICE_H
 #include <QDebug>#include <mutex>
 #include <QDir>
 #include <QTime>
 #include "ctkPluginFrameworkLauncher.h"#include "ctkPluginContext.h"
 #include "ctkPluginException.h"
 #include "ctkPluginFrameworkFactory.h"
 #include "ctkPluginFramework.h"
 #include "ctkPluginException.h"
 #include "ctkPluginContext.h"
 namespace PULLSERVICE{#define PRINTF_LOCATION() qDebug()<<"ret 
                                  in:" << __FILE__ << " 
                                  at:"<<__LINE__
 #define RET_VALUE_IF_NOT_EAQU(a,b,c) \
 do { \
 if(a!=b) \
 { \
 PRINTF_LOCATION();\
 return c; \
 } \
 } while (false)
 #define RET_VALUE_IF_EAQU(a,b,c) \
 do { \
 if(a==b) \
 { \
 PRINTF_LOCATION();\
 return c; \
 } \
 } while (false)
 #define RET_IF_NOT_EAQU(a,b) \
 do { \
 if(a!=b) \
 { \
 PRINTF_LOCATION();\
 return; \
 } \
 } while (false)
 #define RET_IF_EAQU(a,b) \
 do { \
 if(a==b) \
 { \
 PRINTF_LOCATION();\
 return; \
 } \
 } while (false)
 }
 using namespace PULLSERVICE;class AbsUiService;
 class AbsLogService;
 class PullService
 {
 protected:
 virtual ~PullService();
 private:
 PullService();
 // PullService(const PullService&) = delete;
 // PullService& operator=(const PullService&) 
                                  = delete;
 void print(QString info);
 public:
 static PullService* getInstance();
 //对外接口
 void initCtkFramework(bool usingEventAdmin = 
                                  false);//初始化框架
 void initServices();//初始化所有服务
 template<class T>//获取服务,通过模板
 T* getService()
 {
 T* s = nullptr;
 RET_VALUE_IF_EAQU(context,nullptr,s);
 ctkServiceReference reference = context->getServiceReference<T>();
 if(reference)
 {
 s = context->getService<T>(reference);// 
                                  获取指定 ctkServiceReference 引用的服务对象
 if (s == nullptr)
 {
 print("Try to get a invalid service");
 }
 }
 return s;
 }
 void stopFramework();//关闭ctk框架
 private:
 static PullService* instance;
 static std::mutex mMutex;
 volatile bool usingEventAdmin = false;
 private:
 QStringList pluginNames;//所有插件名字
 //ctk相关的变量
 ctkPluginFrameworkFactory frameworkFactory;
 ctkPluginContext* context = nullptr;
 private:
 Q_DISABLE_COPY(PullService)
 };
 #endif // PULLSERVICE_H |  
                            pullservice.cpp 
                             
                              | #include "pullservice.h" //插件头文件
 #include "abslogservice.h"
 #include "absuiservice.h"
 #include "signal.h"
 #include "slot.h"
 #include "absprintserver.h"
 #include "abslogtracker.h"
 PullService* PullService ::instance = nullptr;std::mutex PullService::mMutex;
 PullService::PullService(){
 print("PullService construct");
 pluginNames << "MPrintServer.dll"
 << "ctk-plugin-first.dll"
 << "CreateCtkUiPlugin.dll"
 // << "ctksignalplugin.dll"
 // << "ctkslotplugin.dll"
 << "ctkplugintracker.dll"
 ;
 }
 PullService::~PullService()
 {
 print("PullService destruct");
 }
 PullService* PullService::getInstance(){
 if(nullptr == instance)
 {
 mMutex.lock();
 if(nullptr == instance)
 {
 instance = new PullService;
 }
 mMutex.unlock();
 }
 return instance;
 }
 /*************************///作者:
 //函数名称:初始化ctk框架
 //函数参数:usingEventAdmin是否使用eventadmin
 //函数返回值:NULL
 //函数作用:NULL
 //备注:NULL
 /************************/
 void PullService:: initCtkFramework (bool usingEventAdmin)
 {
 if(nullptr != context)
 {
 print ("ctkPluginContext is not null at 
                                  first time, maybe you have call this method.Try 
                                  restart app to resolve this problem");
 return;
 }
 this->usingEventAdmin = usingEventAdmin;
 if(usingEventAdmin)
 {
 QString path =  QDir::currentPath() +  "/third_libs/ctk/libs"; 
                                  // 获取插件所在位置
 ctkPluginFrameworkLauncher:: addSearchPath(path); 
                                  // 在插件的搜索路径列表中添加一条路径
 ctkPluginFrameworkLauncher:: start ("org.commontk.eventadmin");
 context =  ctkPluginFrameworkLauncher ::getPluginContext();
 }
 else
 {
 QSharedPointer<ctkPluginFramework> framework 
                                  = frameworkFactory.getFramework();
 // 初始化并启动插件框架
 try {
 framework->init();
 framework->start();
 context = framework->getPluginContext();
 } catch  (const ctkPluginException &e) {
 this->print  ("CTK plugin framework init 
                                  failed:"+QString(e.what()));
 }
 }
 }
 /**************************///作者:
 //函数名称:初始化服务
 //函数参数:NULL
 //函数返回值:NULL
 //函数作用:NULL
 //备注:安装启动插件
 /**********************/
 void PullService::initServices()
 {
 RET_IF_EAQU(context,nullptr);
 QString prefixFilePath =  QDir::currentPath()+ "/third_libs/plugin/libs/";
 QString path;
 foreach  (QString oneFileName , pluginNames)
 {
 path = prefixFilePath+oneFileName;
 try {
 // 安装插件
 print(QString("Ready to init plugin:%1").arg(oneFileName));
 QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(path));
 print(QString("Plugin[%1_%2] installed...").arg(plugin->getSymbolicName( )).arg(plugin->getVersion().toString()));
 // 启动插件
 plugin->start(ctkPlugin::START_TRANSIENT);
 print(QString("Plugin[%1_%2]  started...").arg (plugin->getSymbolicName( 
                                  )).arg (plugin->getVersion().toString()));
 } catch  (const ctkPluginException &e) {
 print (QString ("Failed install or start 
                                  plugin:%1").arg (e.what()));
 }
 }
 }
 /**********************///作者:
 //函数名称:停止框架
 //函数参数:NULL
 //函数返回值:NULL
 //函数作用:NULL
 //备注:NULL
 /************************/
 void PullService::stopFramework()
 {
 if(usingEventAdmin)
 {
 ctkPluginFrameworkLauncher::stop();
 }
 else
 {
 QSharedPointer <ctkPluginFramework> framework 
                                  = frameworkFactory.getFramework();
 framework->stop();
 }
 }
 /*************************************/
 //函数名称:内部打印函数
 //函数参数:NULL
 //函数返回值:NULL
 //函数作用:NULL
 //备注:NULL
 /*************************/
 void PullService::print(QString info)
 {
 QString _i = QString("%1 %2 %3")
 .arg(__FILE__)
 .arg(QTime::currentTime( ).toString("HH:mm:ss"))
 .arg(info);
 qDebug()<<_i;
 }
 |   3、main.cpp 
                             
                              | #include <QApplication>//本地头文件 #include "pullservice.h"
 int main(int argc, char *argv[]){
 QApplication a(argc, argv);
 (void)PullService:: getInstance()->initCtkFramework(false);
 (void)PullService:: getInstance()->initServices();
 return a.exec();
 }
 |  
                            4、运行结果 
 |