Qt5下通過CMake建立CTK外掛的步驟
阿新 • • 發佈:2019-01-27
這兩天一直在看CTK外掛的用法,網上資料實在太少,只能通過已有的一些開源工程摸索,過程中遇到很多問題,都是些細節方面的東西,把過程記錄下來,方便以後查閱。網上有通過pro檔案建立外掛的教程,這裡只介紹通過CMakeList配置外掛的方法。
首先新建一個外掛類PluginLoader(名字可以隨意起)
#include <ctkPluginActivator.h> #include <ctkPluginContext.h> 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; };
實現類
因為Q_EXAPORT_PLUGIN2在Qt5中已經廢棄了,這裡加個巨集來判斷。其中ServieOne為服務的實現類,繼承自介面IService,介面供外部呼叫#include "LoadPlugin_p.h" #include <QtPlugin> #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
IService.h:
#include <QObject>
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}
)
因為生成CTK外掛需要一個qrc檔案和MF檔案,ctk提供的ctkMacroBuildPlugin工具可以在建立外掛工程的同時自動建立這兩個檔案,不過需要我們在原始檔目錄下放置兩個cmake檔案manifest_headers.cmake和target_libraries.cmake,檔案內容分別為
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<ctkPluginFramework> 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<ctkPlugin> Plugin = pluginContext->installPlugin(QUrl::fromLocalFile("../liborg_ctk_example.dll"));
Plugin->start(ctkPlugin::START_TRANSIENT);
ctkServiceReference reference = pluginContext->getServiceReference("Service");
IService *test = qobject_cast<IService *>(pluginContext->getService(reference));
test->SetParameter(10);
qDebug() << test->GetParameter();