CTK入门教程08.01:插件加载

系列索引:CTK框架入门教程索引

本文使用CTK框架实现插件加载,流程图为

flowchart LR

A(launcher) --> B[Plugin A]
A --> C[Plugin B]
B --> D[Plugin Activator]
C --> E[Plugin Activator]

插件库

创建工程

打开Qt Creator,新建一个空qmake工程,命名为testPlugin

工程类型

设置pro配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
QT += core
QT -= gui

TARGET = testPlugin
TEMPLATE = lib
CONFIG += plugin

win32:{
INCLUDEPATH += \
D:\CTK-2023.07.13\Libs\Core \
D:\CTK-2023.07.13\Libs\PluginFramework \
D:\CTK-2023.07.13\build\CTK-build\Libs\PluginFramework \
D:\CTK-2023.07.13\build\CTK-build\Libs\Core
}

unix:{
INCLUDEPATH += \
/home/jackey/Downloads/CTK-2023.07.13/Libs/Core \
/home/jackey/Downloads/CTK-2023.07.13/Libs/PluginFramework \
/home/jackey/Downloads/CTK-2023.07.13/build/CTK-build/Libs/PluginFramework \
/home/jackey/Downloads/CTK-2023.07.13/build/CTK-build/Libs/Core
}

给工程添加一个类testPluginActivator

头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef TESTPLUGINACTIVATOR_H
#define TESTPLUGINACTIVATOR_H

#include <QObject>

#include "ctkPluginActivator.h"
#include "ctkPluginContext.h"

class testPluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "testPlugin")
Q_INTERFACES(ctkPluginActivator)
public:
explicit testPluginActivator();
void start(ctkPluginContext *context);
void stop(ctkPluginContext *context);

signals:

};

#endif // TESTPLUGINACTIVATOR_H

类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "testpluginactivator.h"

#include <QDebug>

testPluginActivator::testPluginActivator()
{}

void testPluginActivator::start(ctkPluginContext *context)
{
qDebug() << "first plugin start: " << context;
}

void testPluginActivator::stop(ctkPluginContext *context)
{
qDebug() << "first plugin stop: " << context;
}

元数据

添加一个资源文件,命名为resource.qrc

给资源文件添加一个前缀/testPlugin/META-INF

testPlugin是工程的名字。

再添加一个文本文件MANIFEST.MF,内容为

1
2
Plugin-SymbolicName:testPlugin
Plugin-Version:1.0.0

并把此文件添加到资源文件的前缀下

元数据

编译工程为动态库

插件动态库

测试程序

新建一个Qt控制台程序工程

工程配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
QT += core
QT -= gui

TARGET = test

CONFIG += console
CONFIG -= app_bundle

win32:{
INCLUDEPATH += \
D:\CTK-2023.07.13\Libs\Core \
D:\CTK-2023.07.13\Libs\PluginFramework \
D:\CTK-2023.07.13\build\CTK-build\Libs\PluginFramework \
D:\CTK-2023.07.13\build\CTK-build\Libs\Core

LIBS += -LD:\CTK-2023.07.13\build\CTK-build\bin\Debug \
-lCTKCore -lCTKPluginFramework
}

unix:{
INCLUDEPATH += \
/home/jackey/Downloads/CTK-2023.07.13/Libs/Core \
/home/jackey/Downloads/CTK-2023.07.13/Libs/PluginFramework \
/home/jackey/Downloads/CTK-2023.07.13/build/CTK-build/Libs/PluginFramework \
/home/jackey/Downloads/CTK-2023.07.13/build/CTK-build/Libs/Core

LIBS += -L/home/jackey/Downloads/CTK-2023.07.13/build/CTK-build/bin \
-lCTKCore -lCTKPluginFramework
}


SOURCES += \
main.cpp

在源码中调用框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <QCoreApplication>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFramework.h>
#include <ctkPluginException.h>
#include <ctkPluginContext.h>
#include <QtDebug>
#include <QUrl>

#if defined(Q_OS_WIN)
// 使用mingw编译器时的定义
QString static firstPlugin_filePath = "D:\\Projects\\Qt\\build-testPlugin-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\\debug\\testPlugin.dll";
#elif defined(Q_OS_LINUX)
QString static firstPlugin_filePath = "/home/jackey/Documents/build-testPlugin-Desktop-Debug/libtestPlugin.so";
#endif

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;
}

return a.exec();
}

编译工程为程序

主程序

运行

程序运行输出为

1
2
3
4
5
6
7
8
11:50:03: Starting D:\Projects\Qt\build-test-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\test.exe...
Using database: "D:\\Projects\\Qt\\build-test-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\\debug\\configuration\\plugins.db"
Using database: "D:\\Projects\\Qt\\build-test-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\\debug\\configuration\\plugins.db"
Using database: "D:\\Projects\\Qt\\build-test-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\\debug\\configuration\\plugins.db"
CTK plugin framework start...
"Plugin[testPlugin_1.0.0] installed..."
first plugin start: 0x23d7bcca1a0
Plugin start...

说明

  • 此两个工程将作为后续开发的工程模版

CTK入门教程08.01:插件加载
https://blog.jackeylea.com/ctk/how-to-load-ctk-plugin-library/
作者
JackeyLea
发布于
2024年1月7日
许可协议