• CTK插件-入门打印


    一、生成插件

    0、环境说明

    编译ctk:Qt5.12.2+MSVC2017_64+Cmake

    生成插件:Qt5.12.2+MSVC2017_64+qmake

    1、服务类,纯虚类,提供接口

    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

    2、实现插件类,实现纯虚函数

    logservice.h

    #ifndef LOGSERVICE_H
    #define LOGSERVICE_H
    #include <QObject>
    #include "abslogservice.h"
    
    class ctkPluginContext;
    
    class LogService : public QObject, public AbsLogService
    {
        Q_OBJECT
        Q_INTERFACES(AbsLogService)//表名当前插件类实现这个服务接口
    public:
        LogService(ctkPluginContext* context);
        void log(QString info);
    };
    
    #endif // LOGSERVICE_H

    logservice.cpp

    #include "logservice.h"
    #include <QDebug>
    #include "ctkPluginContext.h"
    #include <QTime>
    LogService::LogService(ctkPluginContext* context)
    {
        context->registerService<AbsLogService>(this);
    }
    
    void LogService::log(QString info)
    {
        qDebug()<<QTime::currentTime().toString("HH:mm:ss    ") + info;//打印加上时间戳
    }

    3、激活插件,加入ctk框架的生命周期中

    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>
    FirstPluginActivator::FirstPluginActivator()
    {
    
    }
    void FirstPluginActivator::start(ctkPluginContext *context)
    {
        qDebug() << "my plugin start";
        m_log.reset(new LogService(context));
    }
    
    void FirstPluginActivator::stop(ctkPluginContext *context)
    {
        qDebug() << "my plugin stop";
        Q_UNUSED(context)
    }

    4、添加资源文件

    资源名随便去,前缀为:TARGET/META_INF,文件名为:MANIFEST.MF

    MANIFEST.MF内容:

     有些教程上说是前缀是工程名/META_INF,经过测试工程名、MANIFEST.MF中的符号名、IID中的字符串都可以随意取,只需要满足这里的前缀是:TARGET/META_INF格式

    有很多可填内容,在ctkPluginConstants.h中能找到相关宏定义

    5、.pro文件

    QT += core
    QT -= gui
    
    TARGET = ctk-plugin-first
    TEMPLATE = lib
    CONFIG += plugin
    #ctk源码路径
    INCLUDEPATH += $$PWD/include/Core 
                += $$PWD/include/PluginFramework
    #ctk安装路径,主要用到ctkPluginFrameworkExport.h等
    INCLUDEPATH += C:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/Libs/PluginFramework
    INCLUDEPATH += C:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/Libs/Core
    #ctk的动态库路径
    LIBS += -LC:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/bin/Debug -lCTKCore -lCTKPluginFramework
    
    HEADERS += 
        firstpluginactivator.h 
        logservice.h 
        abslogservice.h
    
    SOURCES += 
        firstpluginactivator.cpp 
        logservice.cpp
    
    RESOURCES += 
        resource.qrc

    注意:target的名字最好和工程名一致,不然可能出现device not open错误

    6、编译生成插件

    二、使用此插件

    1、main.cpp

    #include <QCoreApplication>
    #include <ctkPluginFrameworkFactory.h>
    #include <ctkPluginFramework.h>
    #include <ctkPluginException.h>
    #include <ctkPluginContext.h>
    #include <QtDebug>
    #include <QUrl>
    
    #include "abslogservice.h"
    
    //插件路径 QString
    static firstPlugin_filePath = "C:/Users/Administrator/Desktop/myctk2017/ctk-plugin-first/debug/ctk-plugin-first.dll"; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); ctkPluginFrameworkFactory frameworkFactory; QSharedPointer<ctkPluginFramework> framework = frameworkFactory.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; } // 获取插件服务的contex ctkPluginContext* 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<AbsLogService>(); if (reference) { // 获取指定 ctkServiceReference 引用的服务对象 AbsLogService* service = qobject_cast<AbsLogService*>(pluginContext->getService(reference)); if (service != Q_NULLPTR) { // 调用服务 service->log("hello hhh.."); } } return a.exec(); }

    2、.pro

    QT -= gui
    
    CONFIG += console
    CONFIG -= app_bundle
    
    INCLUDEPATH += $$PWD/include/Core 
                += $$PWD/include/PluginFramework 
                += $$PWD/include/mydll   #存放插件的服务接口类的头文件
    #ctk的源码
    INCLUDEPATH += C:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/Libs/PluginFramework
    INCLUDEPATH += C:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/Libs/Core
    #ctk的动态库
    LIBS += -LC:/Users/Administrator/Desktop/new/CTK-master/build_msvc2017/CTK-build/bin/Debug -lCTKCore -lCTKPluginFramework
    
    DEFINES += QT_DEPRECATED_WARNINGS
    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

    注意在ctk环境ok的情况下,只需要用到插件的额dll和插件的纯虚类头文件

    3、运行

    ps:附上学习ctk的流程

    1、编译CTK【可用现成的】
    2、编译插件:日志插件【用打印代替存储日志】
    3、新建工程:使用日志插件,并调用接口记录一句话
    4、插件的依赖测试:编写日志插件和打印插件,日志插件依赖打印插件
    5、编写两个插件通信:两种通信方式都需要使用
    6、编写插件:使用服务工厂获取服务
    7、编写插件:监听CTK所有事件
    8、编写插件:使用服务追踪获取服务

  • 相关阅读:
    Python 列表浅拷贝与深拷贝
    Linux 基本命令-----常用操作分类
    硬盘的分区方式
    github中fork的使用
    大O记号
    python的__file__和__name__变量
    python生成器
    python装饰器
    re模块元字符
    python_数据类型_list
  • 原文地址:https://www.cnblogs.com/judes/p/13220386.html
Copyright © 2020-2023  润新知