CTK github地址:GitHub - commontk/CTK: A set of common support code for medical imaging, surgical navigation, and related purposes.
本人已经编译好的CTK库文件下载地址:
https://download.csdn.net/download/wisdomroc/87784048
MANIFEST.MF文件说明:
Plugin-SymbolicName: XxPlugin //插件的符号名,唯一标识
Plugin-ContactAddress: http://www.xx.com.cn //公司网址
Plugin-Description: A plugin impl for Xx //插件描述
Plugin-Name: XxPlugin //插件的名称,对插件起说明作用,不影响插件功能
Plugin-Vendor: org.Xx //供应商
Plugin-Version: 1.0.0 //版本信息
Plugin-Copyright: Copyright 2023 //版权信息
//-----------------------------------------------------------------------------------
Require-Plugin: //插件所需的其他插件的符号名称
Plugin-Localization: //标识插件的Qt(.qm 文件的基本名称:如中文qt_zh.qm,此处写zh)
Plugin-ActivationPolicy: //插件的激活策略
Plugin-UpdateLocation: //在插件更新操作期间,获取新插件版本的位置
MANIFEST.MF文件必须添加在Qt资源文件中,方式如下:
插件加载后会寻找同名前缀/META-INF,所以前缀格式固定,将MANIFEST.MF文件添加进来
<RCC>
<qresource prefix="/Xx/META-INF"> //Xx为插件名称
<file>MANIFEST.MF</file>
</qresource>
</RCC>
插件宏定义文件
#ifndef PLUGINACTIVATORTEMPLATE_H
#define PLUGINACTIVATORTEMPLATE_H
#include "pluginframework/ctkPluginActivator.h"
#define PLUGINACTIVATORDEF(Namespace,ClassName,ServiceName,PluginIID,Q_OBJECT) \
namespace Namespace { \
class ServiceName; \
class ClassName : public QObject, public ctkPluginActivator \
{ \
Q_OBJECT \
Q_PLUGIN_METADATA(IID PluginIID) \
Q_INTERFACES(ctkPluginActivator) \
public: \
explicit ClassName(QObject * parent = nullptr); \
virtual ~ClassName(); \
\
void start(ctkPluginContext *context) override; \
void stop(ctkPluginContext *context) override; \
private: \
ctkPluginContext * context_; \
ServiceName * service_; \
ctkServiceRegistration service_registration_; \
}; \
\
} // namespace Namespace
#define PLUGINACTIVATORIMPL(Namespace,ClassName,ServiceName,ServiceBase) \
namespace Namespace { \
ClassName::ClassName(QObject *parent) \
:QObject(parent), \
context_(nullptr), \
service_(nullptr) \
{ \
\
} \
\
ClassName::~ClassName() \
{ \
if(service_ != nullptr) \
{ \
service_registration_.unregister(); \
delete service_; \
service_ = nullptr; \
} \
} \
\
void ClassName::start(ctkPluginContext *context) \
{ \
if(context == nullptr) \
return; \
service_ = new ServiceName(context); \
service_registration_ = context->registerService<ServiceBase>(service_); \
context_ = context; \
\
}\
\
void ClassName::stop(ctkPluginContext *context) \
{ \
if(context == nullptr) \
return; \
service_registration_.unregister(); \
delete service_; \
context_ = nullptr; \
service_ = nullptr; \
delete this; /* xjh memleak, 临时处理,是为了暂时解决CTK不unload plugin的问题*/\
} \
\
} // namespace Namespace
#endif // PLUGINACTIVATORTEMPLATE_H
快速声明一个插件Activator
#include "PluginActivatorTemplate.h"
PLUGINACTIVATORDEF(Xx,XxActivator,XxService,"org.Xx",Q_OBJECT)
快速定义一个插件Activator
#include "XxActivator.h"
#include "XxService.h"
PLUGINACTIVATORIMPL(Xx,XxActivator,XxService,XxParentService)
其实CTK插件机制,还是应用的Qt的插件机制,只不过使用了中介者模式可以对自定义的插件进行管理并且提供可以互相通信的一个媒介。
Qt的插件机制当然也就是使用Q_DECLARE_INTERFACE、Q_INTERFACES、Q_PLUGIN_METADATA三个宏。
前两个主要是RTTI的实现和插件有效性检测;
第三个宏的作用是插件元信息&元信息获取&插件实例句柄获取的功能。
QPluginLoader→QLibraryPrivate→windows api进行动态库加载/卸载/接口调用。
Qt的插件机制也是建立在Qt元对象系统基础之上的,Qt元对象系统主要提供了Qt的信号槽、RTTI、动态属性系统。
主要是Q_OBJECT宏(定义在qobjectdefs.h中)+元对象编译器进行实现的:
2个成员变量进行元信息&函数列表的存储 + 5个函数进行元对象获取及槽函数调用。
connect会在sender的connectionList中加入相关连接。(回调函数 & postEvent后回调函数)