CTK 框架之多个插件使用同一接口

1、大致流程

 

 

 2、代码实现

接口函数类:

#ifndef WELCOMESERVICE_H
#define WELCOMESERVICE_H
/*
多个插件使用同一接口
*/
#include <QObject>
class WelcomeSerive{
public:
    virtual ~WelcomeSerive(){}
    virtual void welcome() = 0;
};
Q_DECLARE_INTERFACE(WelcomeSerive, "welcome")
#endif // WELCOMESERVICE_H

插件1:

#ifndef SAYQT_H
#define SAYQT_H

#include <QObject>
#include "welcomeservice.h"

class ctkPluginContext;
class SayQT : public QObject,public WelcomeSerive
{
    Q_OBJECT
    Q_INTERFACES(WelcomeSerive)
public:
    SayQT();
    void welcome();
};

#endif // SAYQT_H

.cpp

#include "sayqt.h"
#include "ctkPluginContext.h"
#include <QDebug>

SayQT::SayQT()
{

}

void SayQT::welcome()
{
    qDebug()<<"Hello QT";
}

插件2

#ifndef SAYWELCOME_H
#define SAYWELCOME_H

#include <QObject>
#include "welcomeservice.h"

class ctkPluginContext;
class SayWelcome : public QObject, public WelcomeSerive
{
    Q_OBJECT
    Q_INTERFACES(WelcomeSerive)
public:
    SayWelcome();
    void welcome();
};

#endif // SAYWELCOME_H

.cpp

#include "saywelcome.h"
#include <QDebug>
#include "ctkPluginContext.h"

SayWelcome::SayWelcome()
{

}

void SayWelcome::welcome()
{
    qDebug()<<"welcome CTK";
}

注册类

#ifndef SENCONDSERVICE_H
#define SENCONDSERVICE_H

#include <QObject>
#include "ctkPluginContext.h"
#include "ctkPluginActivator.h"
#include "saywelcome.h"
#include "sayqt.h"

class sencondService : public QObject,public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "welasdcome")
public:
    sencondService();
    void start(ctkPluginContext *context);
    void stop(ctkPluginContext *context);
};

#endif // SENCONDSERVICE_H

.cpp

#include "sencondservice.h"
#include "ctkDictionary.h"

sencondService::sencondService()
{

}

void sencondService::start(ctkPluginContext *context)
{
    ctkDictionary properties;   //插件1
    properties.insert(ctkPluginConstants::SERVICE_RANKING, 1);
    properties.insert("name", "CTK");
    SayWelcome *m_pImpl = new SayWelcome();
    context->registerService<WelcomeSerive>(m_pImpl, properties);

//    ctkDictionary properties; //  插件2
    properties.insert(ctkPluginConstants::SERVICE_RANKING, 2);
    properties.insert("name", "QT");
    SayQT *pImpl = new SayQT();
    context->registerService<WelcomeSerive>(pImpl, properties);
}

void sencondService::stop(ctkPluginContext *context)
{
    Q_UNUSED(context);
}

资源文件:

 

 

 红色的标记表示的是工程名。

MANIFEST.MF内容

Plugin-SymbolicName:TwoTest
Plugin-Version:1.0.0

其中

Plugin-SymbolicName:TwoTest是必须要得,TwoTest这个可随便取。

.pro文件
QT += core
QT -= gui

TARGET = WelcomeCTK
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 += \
    welcomeservice.h \
    saywelcome.h \
    sencondservice.h \
    sayqt.h \
#    welcome_ctk.h

SOURCES += \
    saywelcome.cpp \
    sencondservice.cpp \
    sayqt.cpp \
#    welcome_ctk.cpp

RESOURCES += \
    pro.qrc

 

ctk插件的调用

.pro文件

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle


INCLUDEPATH += C:/Users/ch-pc/Desktop/CTK-master/Libs/Core \
            += C:/Users/ch-pc/Desktop/CTK-master/Libs/PluginFramework \

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

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

main.cpp文件

#include <QCoreApplication>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFramework.h>
#include <ctkPluginException.h>
#include <ctkPluginContext.h>
#include <QtDebug>
#include <QUrl>
#include "welcomeservice.h"

QString static firstPlugin_filePath = "D:/program object/WelcomeCTK/debug/WelcomeCTK.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;
    }
    // 获取服务引用
    QList<ctkServiceReference> refs = pluginContext->getServiceReferences<WelcomeSerive>();
    foreach (ctkServiceReference ref, refs)
    {
        if (ref)
        {
            qDebug() << "Name:" << ref.getProperty("name").toString()<< "Service ranking:" <<ref.getProperty(ctkPluginConstants::SERVICE_RANKING).toLongLong()<< "Service id:" <<ref.getProperty(ctkPluginConstants::SERVICE_ID).toLongLong();
            WelcomeSerive* service = qobject_cast<WelcomeSerive *>(pluginContext->getService(ref));
            if (service != Q_NULLPTR)
                service->welcome();
        }
    }
    qDebug() << "********************";
    return a.exec();
}

运行结果:

 

 

 

总结:
在注册两插件时,我开始定义了两个
cpp,但是报了一个错误

 

 

 

 

 具体产生的原因好像是在一个动态库只能调用一次Q_PLUGIN_METADATA(IID "welasdcome")这个。所以我删除了一个cpp把它注册插件的内容放在了一个cpp里面。

 

在进行插件之间通信时,需要主要一般是先调用接收事件的插件,然后在调用发送事件的插件

 

posted on 2020-07-13 16:37  缘随风烬  阅读(730)  评论(0编辑  收藏  举报