这两天一直在看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;
};

实现类

#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
因为Q_EXAPORT_PLUGIN2在Qt5中已经废弃了,这里加个宏来判断。其中ServieOne为服务的实现类,继承自接口IService,接口供外部调用

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();


Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐