Qt 插件机制使用及原理_qt插件机制-****博客
目录
1.接口(interface)
2.插件(Plugin)
3.服务(Service)
4.接口、插件、服务之间的关系
5.总结
1.接口(interface)
1) 定义:接口在CTK插件框架中通常指纯虚函数类,即只包含纯虚函数的类,用于定义插件对外提供的服务规范。接口类只声明了服务的功能,而不包含具体的实现。
2) 作用:接口作为服务的前身,定义了插件之间通信的契约。其他插件或应用程序通过接口来调用插件提供的服务,而无需关心服务的具体实现细节。
3) 示例:在CTK插件框架中,可以定义一个名为HelloService
的接口类,该类包含一个纯虚函数sayHello()
,用于输出“Hello, CTK!”的字符串。
hello_service.h
#ifndef HELLO_SERVICE_H
#define HELLO_SERVICE_H
#include <QtPlugin>
class HelloService
{
public:
virtual ~HelloService() {}
virtual void sayHello() = 0;
};
#define HelloService_iid "org.commontk.service.demos.HelloService"
Q_DECLARE_INTERFACE(HelloService, HelloService_iid)
#endif // HELLO_SERVICE_H
2.插件(Plugin)
1) 定义:插件是实现接口类的具体类,即插件是接口的实现者。每个插件都包含了一个或多个接口的实现类,以及一个激活类(Activator),负责将插件的服务注册到CTK的服务注册中心。
2) 作用:插件是CTK插件框架中的基本构建块,它们提供了应用程序所需的具体功能。通过插件,应用程序可以动态地扩展和更新其功能,而无需修改应用程序本身的代码。
3) 示例:在上面的HelloService
接口示例中,可以编写一个名为HelloImpl
的插件实现类,该类继承自QObject
和HelloService
接口,并实现sayHello()
函数的具体逻辑。
hello_impl.h
#ifndef HELLO_IMPL_H
#define HELLO_IMPL_H
#include "hello_service.h"
#include <QObject>
class ctkPluginContext;
class HelloImpl : public QObject, public HelloService
{
Q_OBJECT
Q_INTERFACES(HelloService)
public:
HelloImpl(ctkPluginContext* context);
void sayHello() Q_DECL_OVERRIDE;
};
#endif // HELLO_IMPL_H
hello_impl.cpp
#include "hello_impl.h"
#include <ctkPluginContext.h>
#include <QtDebug>
HelloImpl::HelloImpl(ctkPluginContext* context)
{
context->registerService<HelloService>(this);
}
void HelloImpl::sayHello()
{
qDebug() << "Hello,CTK!";
}
3.服务(Service)
1) 定义:服务是根据接口实例化的对象,是插件向外部提供的功能单元。每个服务都对应一个接口的实现,并通过CTK的服务注册中心进行注册和发现。
2) 作用:服务是插件之间通信的桥梁。当其他插件或应用程序需要调用某个插件的功能时,它们会通过服务注册中心查找并获取相应的服务实例,然后调用该实例上的方法来执行所需的操作。
3) 示例:在CTK插件框架中,当HelloImpl
插件被加载并激活后,它会将其实现的HelloService
服务注册到服务注册中心。其他插件或应用程序可以通过服务注册中心获取HelloService
服务的实例,并调用sayHello()
方法来输出“Hello, CTK!”的字符串。
#include <QCoreApplication>
#include <QDirIterator>
#include <QtDebug>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFramework.h>
#include <ctkPluginException.h>
#include <ctkPluginContext.h>
#include "../Service/hello_service.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
ctkPluginFrameworkFactory frameWorkFactory;
QSharedPointer<ctkPluginFramework> framework = frameWorkFactory.getFramework();
try {
// 初始化并启动插件框架
framework->init();
framework->start();
qDebug() << "CTK Plugin Framework start ...";
} catch (const ctkPluginException &e) {
qDebug() << "Failed to initialize the plugin framework: " << e.what();
return -1;
}
qDebug() << "********************";
// 获取插件上下文
ctkPluginContext* context = framework->getPluginContext();
// 获取插件所在位置
QString path = QCoreApplication::applicationDirPath() + "/plugins";
// 遍历路径下的所有插件
QDirIterator itPlugin(path, QStringList() << "*.dll" << "*.so", QDir::Files);
while (itPlugin.hasNext()) {
QString strPlugin = itPlugin.next();
try {
// 安装插件
QSharedPointer<ctkPlugin> plugin = context->installPlugin(QUrl::fromLocalFile(strPlugin));
// 启动插件
plugin->start(ctkPlugin::START_TRANSIENT);
qDebug() << "Plugin start:" << QFileInfo(strPlugin).fileName();
} catch (const ctkPluginException &e) {
qDebug() << "Failed to start plugin" << e.what();
return -1;
}
}
qDebug() << "********************";
// 1. 获取所有服务
QList<ctkServiceReference> refs = context->getServiceReferences<HelloService>();
foreach (ctkServiceReference ref, refs) {
if (ref) {
HelloService* service = qobject_cast<HelloService*>(context->getService(ref));
if (service != Q_NULLPTR)
service->sayHello();
}
}
return app.exec();
}
4.接口、插件、服务之间的关系
1) 接口与插件:一个接口可以由一个或多个插件实现,每个插件都提供了接口的一个具体实现。插件通过实现接口来定义其对外提供的服务。
2)插件与服务:一个插件可以注册多个服务,每个服务都对应一个接口的实现。插件通过激活类将其实现的服务注册到CTK的服务注册中心,以便其他插件或应用程序进行调用。
3)服务与接口:服务是接口的具体实例,是插件之间通信的实体。服务通过接口定义的契约进行交互,确保了插件之间的松耦合和可替换性。
下面是接口、插件和服务的几种对应关系:
1对1:
1个接口类由1个具体类实现,输出1个服务和1个插件。
多对1:
1个具体类实现了2个接口类,输出2个服务和1个插件,无论想使用哪个服务最终都通过这同一个插件来实现
1对多:
1接口由2个类实现,也就是某一个问题提供了2种解决思路,输出1个服务和2个插件,通过ctkPluginConstants::SERVICE_RANKING和ctkPluginConstants::SERVICE_ID来调用不同的插件。这里虽然有两个插件,但都是被编译到同一个dll中的。
在后面的讲解中都会一一举例说明这些情况的。
5.总结
综上所述,CTK插件框架中的接口、插件、服务是三个紧密相关的概念,它们共同构成了一个可扩展、可复用的应用程序架构。通过这三个概念的灵活应用,可以构建出功能丰富、易于维护的生物医学图像计算应用程序。
源码地址:octo/CTK-examples