CTK Plugin Framework中创建插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyy626562203/article/details/82781833

CTK Plugin Framework中创建插件

CTK 源码中有一部分插件相关的示例,进入 CTK-master/Libs/PluginFramework/Testing 目录

使用cmake构建插件

由于CTK 插件框架是基于Qt 实现的,所以插件的创建也符合Qt 的标准。

创建插件

首先,定义一个测试的接口类,包含了服务提供的功能。

test_plugin_service.h内容如下:

#ifndef TEST_PLUGIN_SERVICE_H
#define TEST_PLUGIN_SERVICE_H

#include <QtPlugin>
#include <QString>

class TestPluginService 
{
public:
    virtual ~TestPluginService() {}
    virtual bool test(const QString& username, const QString& password) = 0;
};

#define TestService_iid "org.commontk.service.TestService"

Q_DECLARE_INTERFACE(TestPluginService, TestService_iid)

#endif // Test_PLUGIN_SERVICE_H

使用 Q_DECLARE_INTERFACE 宏让Qt元对象系统感知到该接口,可在运行时识别实现了该接口的插件。

注意:TestService_iid是一个标识接口的字符串且必须唯一。

接着为该接口定义一个实现类TestPlugin。让子类实现接口到同时继承QObject,使这个类成为一个插件。

test_plugin.h 内容如下:

#ifndef TEST_PLUGIN_H
#define TEST_PLUGIN_H

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

class ctkPluginContext;

class TestPlugin : public QObject, public TestPluginService
{
    Q_OBJECT
    Q_INTERFACES(TestPluginService)

public:
    TestPlugin(ctkPluginContext* context);
    bool test(const QString& username, const QString& password) Q_DECL_OVERRIDE;
};

#endif // TEST_PLUGIN_H

Q_INTERFACES宏用于告诉Qt该类实现的接口。

实现一个简单的登录例子,假设用户名为 "root",密码为 "root" ,登录成功返回true否则,登录失败。

test_plugin.cpp 内容如下:

#include "test_plugin.h"
#include <ctkPluginContext.h>

TesthPlugin::TestPlugin(ctkPluginContext* context)
{
    context->registerService<TestPluginService>(this);
}

bool TestPlugin::test(const QString& username, const QString& password)
{
    if (QString::compare(username, "root") == 0
            && QString::compare(password, "root") == 0) {
        return true;
    } else {
        return false;
    }
}

ctkPluginContext类是CTK 插件的上下文,将服务注册给它,在需要时就可以直接获取了。

注意: ctkPluginContext 是与运行框架交互的唯一方法。

除此之外,还需要为插件提供一个生命周期类。该类继承自CTKPlugin中的 ctkPluginActivator,在 ctkPluginActivator中提供了两个虚函数 start()stop(),通过实现生命周期类来完成服务的注册。

test_plugin_activator.h 内容如下:

#ifndef TEST_PLUGIN_ACTIVATOR_H
#define TEST_PLUGIN_ACTIVATOR_H

#include <ctkPluginActivator.h>
#include "test_plugin_service.h"

class TestPluginActivator : public QObject,
        public ctkPluginActivator
{
    Q_OBJECT
    Q_INTERFACES(ctkPluginActivator)
    Q_PLUGIN_METADATA(IID "test_plugin")

public:
    void start(ctkPluginContext* context);
    void stop(ctkPluginContext* context);

private:
    QScopedPointer<TestPluginService> service;
};

#endif // TEST_PLUGIN_ACTIVATOR_H

使用 registerService()CTKPlugin 插件系统中注册该插件时会调用start()生命周期的开始 ,而 stop() 则是插件生命周期的终止。

test_plugin_activator.cpp 内容如下:

#include "test_plugin_activator.h"
#include "test_plugin.h"

void TestPluginActivator::start(ctkPluginContext* context)
{
    service.reset(new TestPlugin(context));
}

void TestPluginActivator::stop(ctkPluginContext* context)
{
    Q_UNUSED(context)
}

配置插件

由于CTK采用CMake来构建的,下面就使用CMake来配置CTK插件。

CMakeList.txt 内容如下:

project(test_plugin)

set(PLUGIN_export_directive "test_plugin_export")

set(PLUGIN_SRCS
    test_plugin.cpp
    test_plugin_activator.cpp
    test_plugin_service.h
)

set(PLUGIN_MOC_SRCS
    test_plugin.h
    test_plugin_activator.h
)

set(PLUGIN_resources

)

ctkFunctionGetTargetLibraries(PLUGIN_target_libraries)

ctkMacroBuildPlugin(
    NAME ${PROJECT_NAME}
    EXPORT_DIRECTIVE ${PLUGIN_export_directive}
    SRCS ${PLUGIN_SRCS}
    MOC_SRCS ${PLUGIN_MOC_SRCS}
    RESOURCES ${PLUGIN_resources}
    TARGET_LIBRARIES ${PLUGIN_target_libraries}
    TEST_PLUGIN
)

其中必须包含一个 project 命令,项目名必须对应于插件的目录名。

PLUGIN_export_directive 是导出相关的指令,应该使用与 xxx_export.h 文件中相同的标记 # define <export-directive> Q_DECL_EXPORT

在生成CTK插件时,需要一个 qrc 文件和 MF 文件。CTK提供的ctkMacroBuildPlugin工具可以在创建插件工程的同时自动创建这两个文件,不过需要在源文件目录下放置两个 cmake 文件 manifest_headers.cmaketarget_libraries.cmake

manifest_headers.cmake 主要包含插件的元信息:

set(Plugin-ActivationPolicy "eager")
set(Plugin-Name "test_plugin")
set(Plugin-Version "1.0.0")
set(Plugin-Description "a plugin for test")
set(Plugin-Vendor "test")
set(Plugin-ContactAddress "https://test.com/test")
set(Plugin-Category "test")

target_libraries.cmake 用于列出构建当前CTK插件所需的库:

set(target_libraries
    CTKPluginFramework
)

完成以上步骤,将插件放置到CTK 源码包CTK-master/Libs/PluginFramework/Testing/FrameworkTestPlugins 中,这样以来,在编译 CTK 时也可以编译我们自己的插件。

除此之外,还需要修改 CTK-master/Libs/PluginFramework/Testing 中的 CMakeLists.txt 文件,将我们的插件添加进去。

编译插件

重新编译CTK,插件编译成功,也生成了qrc 文件和 MF 文件。

使用qmake构建插件

需要的文件

创建CTK插件时,需要一个 qrc 文件和 MF 文件。在使用CMake编译插件时可以在目录中找到这两个文件,其中MANIFEST.MF 是插件属性(包含:符号名、插件名、版本号等)文件:

Plugin-SymbolicName: test.plugin
Plugin-ActivationPolicy: eager
Plugin-Category: test
Plugin-ContactAddress: https://test.com/test
Plugin-Description: A plugin for test 
Plugin-Name: test_plugin
Plugin-Vendor: test
Plugin-Version: 1.0.0

test_plugin_manifest.qrc 是资源集合文件:

<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/test.plugin/META-INF">
    <file>MANIFEST.MF</file>
</qresource>
</RCC>

将资源文件编译成二进制,以便在程序中访问。

创建插件

了解了 qrcMF 文件,创建插件变得十分简单。

CMake 和 qmake 相比:

  • CMake:需要 CMakeList.txtmanifest_headers.cmaketarget_libraries.cmake
  • qmake:需要 .protest_plugin_manifest.qrcMANIFEST.MF

除此之外,其他文件(例如:test_plugin_service.h)则保持不变。

注意: 其他文件内容请参考上面代码

这个是 .pro 文件:

QT += core
QT -= gui

TEMPLATE = lib
CONFIG += plugin
TARGET = test_plugin

LIBS += -L$$PWD/Libs -lCTKCore -lCTKPluginFramework

INCLUDEPATH += \
    $$PWD/../../CTK-master/Libs/Core \
    $$PWD/../../CTK-master/Libs/PluginFramework

HEADERS += \
    test_plugin_service.h \
    test_plugin.h \
    test_plugin_activator.h

SOURCES += \
    test_plugin.cpp \
    test_plugin_activator.cpp

RESOURCES += testplugin_manifest.qrc

由于构建的是一个共享库,所以需要将 TEMPLATE 设置为 lib,同时还必须将 CONFIG 设置为 plugin

创建 CTK 插件时,需要依赖 CTKCoreCTKPluginFramework,所以也要将他们包含进来。

最后,记得使用 RESOURCES 指定资源集合文件。

编译加载

编译生成 tset_plugin.dll

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/82781833