zoukankan      html  css  js  c++  java
  • CTK-使用ctk框架完成日志、打印、界面插件

     一、项目介绍

    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

    #ifndef ABSLOGSERVICE_H
    #define ABSLOGSERVICE_H
    
    #include <QObject>
    class AbsLogService{
    public:
        virtual ~AbsLogService(){}
        virtual void log(QString info) = 0;
    };
    Q_DECLARE_INTERFACE(AbsLogService,"judesmorning.zxy.AbsLogService")
    
    
    #endif // ABSLOGSERVICE_H

    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

    #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       += core
    QT += 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、运行结果

  • 相关阅读:
    ADO.NET FOR MySQL帮助类
    遍历文件夹及其子文件夹下的.pdf文件,并解压文件夹下所有的压缩包
    history.back();谷歌浏览器,iframe后退问题
    Request.url请求属性
    正则表达式 取两字符中间的字符串(双向非贪婪模式)
    MVC 项目中为什么会有两个web.config
    c#动态编译并动态生成dll
    siteserver cms选择栏目搜索无效
    jquery修改Switchery复选框的状态
    ntko office在线编辑控件问题记录
  • 原文地址:https://www.cnblogs.com/judes/p/13285743.html
Copyright © 2011-2022 走看看