这两天一直在看CTK插件的用法,网上资料实在太少,只能通过已有的一些开源工程摸索,过程中遇到很多问题,都是些细节方面的东西,把过程记录下来,方便以后查阅。网上有通过pro文件创建插件的教程,这里只介绍通过CMakeList配置插件的方法。
首先新建一个插件类PluginLoader(名字可以随意起)
#include
#include
class ServiceOne;
class LoadPlugin : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_INTERFACES(ctkPluginActivator)
#ifdef HAVE_QT5
Q_PLUGIN_METADATA(IID "org_ctk_example")
#endif
public:
LoadPlugin();
void start(ctkPluginContext *Context);
void stop(ctkPluginContext *Context);
private:
ServiceOne *m_service;
};
实现类
#include "LoadPlugin_p.h"
#include
#include "ServiceOne.h"
LoadPlugin::LoadPlugin():m_service(0)
{
}
void LoadPlugin::start(ctkPluginContext *Context)
{
m_service = new ServiceOne;
Context->registerService(QStringList("Service"), m_service);
}
void LoadPlugin::stop(ctkPluginContext *Context)
{
if (m_service)
{
delete m_service;
m_service = 0;
}
}
#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
Q_EXPORT_PLUGIN2(org_commontk_log, ctkLogPlugin)
#endif
因为Q_EXAPORT_PLUGIN2在Qt5中已经废弃了,这里加个宏来判断。其中ServieOne为服务的实现类,继承自接口IService,接口供外部调用
IService.h:
#include
class IService :public QObject
{
Q_OBJECT
public:
virtual void SetParameter(int x) = 0;
virtual int GetParameter() = 0;
};
Q_DECLARE_INTERFACE(IService, "Service")
ServiceOne.h
#include "IService.h"
#include "QObject"
class ServiceOne : public IService
{
Q_OBJECT
Q_INTERFACES(IService)
public:
ServiceOne() {}
~ServiceOne() {}
void SetParameter(int x) { m_x = x; }
int GetParameter() { return m_x; }
private:
int m_x;
};
下面是CMakeList.txt中的内容
project(org_ctk_example)
set(PLUGIN_export_directive "org_ctk_example_EXPORT")
find_package(CTK REQUIRED)
include_directories(
${CTKCore_INCLUDE_DIRS}
${CTKPluginFramework_INCLUDE_DIRS}
)
set(PLUGIN_SRCS
LoadPlugin.cxx
)
# Files which should be processed by Qts moc
set(PLUGIN_MOC_SRCS
LoadPlugin_p.h
IService.h
ServiceOne.h
)
# Qt Designer files which should be processed by Qts uic
set(PLUGIN_UI_FORMS
)
# QRC Files which should be compiled into the plugin
set(PLUGIN_resources
)
#Compute the plugin dependencies
ctkFunctionGetTargetLibraries(PLUGIN_target_libraries)
ctkMacroBuildPlugin(
NAME ${PROJECT_NAME}
EXPORT_DIRECTIVE ${PLUGIN_export_directive}
Hdrs ${Headers}
SRCS ${PLUGIN_SRCS}
MOC_SRCS ${PLUGIN_MOC_SRCS}
UI_FORMS ${PLUGIN_UI_FORMS}
RESOURCES ${PLUGIN_resources}
TARGET_LIBRARIES ${PLUGIN_target_libraries}
)
manifest_headers.cmake
set(Plugin-Name "CTK Example")
set(Plugin-ActivationPolicy "eager")
Plugin-name为插件名称,可以自己设置。
arget_libraries.cmake:
SET(target_libraries
CTKPluginFramework
)
创建好这两个文件,通过cmake配置我们的工程,在生成目录下就会生成MANIFEST.MF和org_ctk_example_manifest.qrc两个文件了。生成好的插件通过Dependency Walker查看,需要有两个导出函数qt_plugin_instance和qt_plugin_query_metadata,否则说明插件配置有问题(刚开始因为一些细节插件总是生成失败T_T)。
生成成功后就可以加载插件并调用服务了
ctkPluginFrameworkFactory* ctkFrameWorkFactory = new ctkPluginFrameworkFactory;
QSharedPointer framework = ctkFrameWorkFactory->getFramework();
try
{
framework->init();
framework->start();
qDebug() << "[Info] ctkPluginFramework start ...";
}
catch (const ctkPluginException &Exception)
{
qDebug() << QObject::tr("Failed to initialize the plug-in framework: ") << Exception.what();
return 1;
}
//install plugin
ctkPluginContext* pluginContext = framework->getPluginContext();
QSharedPointer Plugin = pluginContext->installPlugin(QUrl::fromLocalFile("../liborg_ctk_example.dll"));
Plugin->start(ctkPlugin::START_TRANSIENT);
ctkServiceReference reference = pluginContext->getServiceReference("Service");
IService *test = qobject_cast(pluginContext->getService(reference));
test->SetParameter(10);
qDebug() << test->GetParameter();