• CTK框架(二): 接口、插件和服务


    Qt 插件机制使用及原理_qt插件机制-CSDN博客

    目录

    1.接口(interface)

    2.插件(Plugin)

    3.服务(Service)

    4.接口、插件、服务之间的关系

    5.总结


    1.接口(interface)

    1) 定义:接口在CTK插件框架中通常指纯虚函数类,即只包含纯虚函数的类,用于定义插件对外提供的服务规范。接口类只声明了服务的功能,而不包含具体的实现。

    2) 作用:接口作为服务的前身,定义了插件之间通信的契约。其他插件或应用程序通过接口来调用插件提供的服务,而无需关心服务的具体实现细节。

    3) 示例:在CTK插件框架中,可以定义一个名为HelloService接口类,该类包含一个纯虚函数sayHello(),用于输出“Hello, CTK!”的字符串

    hello_service.h

    1. #ifndef HELLO_SERVICE_H
    2. #define HELLO_SERVICE_H
    3. #include
    4. class HelloService
    5. {
    6. public:
    7. virtual ~HelloService() {}
    8. virtual void sayHello() = 0;
    9. };
    10. #define HelloService_iid "org.commontk.service.demos.HelloService"
    11. Q_DECLARE_INTERFACE(HelloService, HelloService_iid)
    12. #endif // HELLO_SERVICE_H

    2.插件(Plugin)

    1) 定义:插件是实现接口类的具体类,即插件是接口的实现者。每个插件都包含了一个或多个接口的实现类,以及一个激活类(Activator),负责将插件的服务注册到CTK的服务注册中心。

    2) 作用:插件是CTK插件框架中的基本构建块,它们提供了应用程序所需的具体功能。通过插件,应用程序可以动态地扩展和更新其功能,而无需修改应用程序本身的代码。

    3) 示例:在上面的HelloService接口示例中,可以编写一个名为HelloImpl的插件实现类,该类继承自QObjectHelloService接口,并实现sayHello()函数的具体逻辑。

    hello_impl.h

    1. #ifndef HELLO_IMPL_H
    2. #define HELLO_IMPL_H
    3. #include "hello_service.h"
    4. #include
    5. class ctkPluginContext;
    6. class HelloImpl : public QObject, public HelloService
    7. {
    8. Q_OBJECT
    9. Q_INTERFACES(HelloService)
    10. public:
    11. HelloImpl(ctkPluginContext* context);
    12. void sayHello() Q_DECL_OVERRIDE;
    13. };
    14. #endif // HELLO_IMPL_H

    hello_impl.cpp

    1. #include "hello_impl.h"
    2. #include
    3. #include
    4. HelloImpl::HelloImpl(ctkPluginContext* context)
    5. {
    6. context->registerService(this);
    7. }
    8. void HelloImpl::sayHello()
    9. {
    10. qDebug() << "Hello,CTK!";
    11. }

    3.服务(Service)

    1) 定义:服务是根据接口实例化的对象,是插件向外部提供的功能单元。每个服务都对应一个接口的实现,并通过CTK的服务注册中心进行注册和发现。

    2) 作用:服务是插件之间通信的桥梁。当其他插件或应用程序需要调用某个插件的功能时,它们会通过服务注册中心查找并获取相应的服务实例,然后调用该实例上的方法来执行所需的操作。

    3) 示例:在CTK插件框架中,当HelloImpl插件被加载并激活后,它会将其实现的HelloService服务注册到服务注册中心。其他插件或应用程序可以通过服务注册中心获取HelloService服务的实例,并调用sayHello()方法来输出“Hello, CTK!”的字符串。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include "../Service/hello_service.h"
    9. int main(int argc, char *argv[])
    10. {
    11. QCoreApplication app(argc, argv);
    12. ctkPluginFrameworkFactory frameWorkFactory;
    13. QSharedPointer framework = frameWorkFactory.getFramework();
    14. try {
    15. // 初始化并启动插件框架
    16. framework->init();
    17. framework->start();
    18. qDebug() << "CTK Plugin Framework start ...";
    19. } catch (const ctkPluginException &e) {
    20. qDebug() << "Failed to initialize the plugin framework: " << e.what();
    21. return -1;
    22. }
    23. qDebug() << "********************";
    24. // 获取插件上下文
    25. ctkPluginContext* context = framework->getPluginContext();
    26. // 获取插件所在位置
    27. QString path = QCoreApplication::applicationDirPath() + "/plugins";
    28. // 遍历路径下的所有插件
    29. QDirIterator itPlugin(path, QStringList() << "*.dll" << "*.so", QDir::Files);
    30. while (itPlugin.hasNext()) {
    31. QString strPlugin = itPlugin.next();
    32. try {
    33. // 安装插件
    34. QSharedPointer plugin = context->installPlugin(QUrl::fromLocalFile(strPlugin));
    35. // 启动插件
    36. plugin->start(ctkPlugin::START_TRANSIENT);
    37. qDebug() << "Plugin start:" << QFileInfo(strPlugin).fileName();
    38. } catch (const ctkPluginException &e) {
    39. qDebug() << "Failed to start plugin" << e.what();
    40. return -1;
    41. }
    42. }
    43. qDebug() << "********************";
    44. // 1. 获取所有服务
    45. QList refs = context->getServiceReferences();
    46. foreach (ctkServiceReference ref, refs) {
    47. if (ref) {
    48. HelloService* service = qobject_cast(context->getService(ref));
    49. if (service != Q_NULLPTR)
    50. service->sayHello();
    51. }
    52. }
    53. return app.exec();
    54. }

    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

  • 相关阅读:
    Java#数据结构----2
    Node.js | 使用 zlib 内置模块进行 gzip 压缩
    用向量数据库Milvus Cloud搭建检索知识库机器人
    科技资讯|AirPods Pro基于定位控制的自适应音频功能
    AI人工智能填词,唱响心中独特旋律
    行为设计模式之职责链模式
    【Axure教程】拖拉拽移动地图
    数字化时代——如何快速实现数字化转型并进入低代码赛道
    Layui自定义列表多选
    DevOps持续部署的关键要素
  • 原文地址:https://blog.csdn.net/haokan123456789/article/details/140451712