ctk框架由一个一个可分离的插件组成,框架对插件识别有一定要求,目前网上很多一整块扔出来对新人不太友好,博主这里讲解是尽量拆。单个插件最基本的格式要求分成Activator,qrc文件,以及MANIFEST.MF,我们以生成一个主界面模块MainWindow为例。
Activator
右键项目选择新建子项目-其他项目-Empty qmake Project,项目名称为MainWindow,pro文件中添加代码:
TEMPLATE = lib
TARGET = MainWindow
DESTDIR = $$PWD/../bin/plugins/$$TARGET
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
#加载ctk库
macx: LIBS += -L$$PWD/../libs/ -lCTKCore.0.1.0
macx: LIBS += -L$$PWD/../libs/ -lCTKPluginFramework.0.1.0
INCLUDEPATH += $$PWD/../inclues \
+= $$PWD/../includes/core \
+= $$PWD/../includes/pluginFramework
INCLUDEPATH += $$PWD/../libs
DEPENDPATH += $$PWD/../libs
项目中添加C++类MainWindowActivator,代码如下:
mainwindowactivator.h
#ifndef MAINWINDOWACTIVATOR_H
#define MAINWINDOWACTIVATOR_H
#include <QObject>
#include "ctkPluginActivator.h"
class MainWindowActivator : public QObject, public ctkPluginActivator
{
public:
Q_OBJECT
Q_PLUGIN_METADATA(IID "MainWindow")
Q_INTERFACES(ctkPluginActivator)
public:
MainWindowActivator();
void start(ctkPluginContext *context);
void stop(ctkPluginContext *context);
};
#endif // MAINWINDOWACTIVATOR_H
mainwindowactivator.cpp
#include "mainwindowactivator.h"
#include <QDebug>
MainWindowActivator::MainWindowActivator()
{
}
void MainWindowActivator::start(ctkPluginContext *context)
{
qDebug() << "mainwindow start";
}
void MainWindowActivator::stop(ctkPluginContext *context)
{
}
activator是标准的Qt插件类,它实现ctkPluginActivator的start、stop函数并对外提供接口。我这里是Qt5的版本,所以使用Q_PLUGIN_METADATA申明插件,Qt4需要用自己的方法实现插件。
qrc文件
创建插件的资源文件,格式如下:
<RCC> <qresource prefix="/MainWindow/META-INF"> <file>MANIFEST.MF</file> </qresource> </RCC>
插件加载后会寻找同名前缀/META-INF,所以前缀格式固定,将MANIFEST.MF文件添加进来
MENIFEST.MF
MENIFEST.MF文件内容如下:
Plugin-SymbolicName:MainWindow
Plugin-Version:1.0.0
文件包含ctk插件的基本信息,只要ctk框架正常识别到文件中Plugin-SymbolicName等信息,则判定它是一个ctk插件,能够正常调用activator中的start、stop函数。这个文件需要拷到插件生成路径下,pro文件中添加代码:
file.path = $$DESTDIR
file.files = MANIFEST.MF
INSTALLS += file
记得在项目构建里面,加上make参数install
ctk插件启用
根据以上步骤,一个ctk插件接口定义基本完成,我们在console项目下调用观察插件是否能够正常加载。main函数中框架启动成功后添加以下代码:
QString dir = QCoreApplication::applicationDirPath();
dir += "/plugins/MainWindow/libMainWindow.dylib";
qDebug() << dir;
QUrl url = QUrl::fromLocalFile(dir);
QSharedPointer<ctkPlugin> plugin;
try
{
plugin = framework->getPluginContext()->installPlugin(url);
}catch(ctkPluginException e){
qDebug() << e.message() << e.getType();
}
try{
plugin->start(ctkPlugin::START_TRANSIENT);
}catch(ctkPluginException e){
qDebug() << e.message() << e.getType();
}
控制台打印输出:
"/Users/Shared/qt/ctkExample/bin/plugins/MainWindow/libMainWindow.dylib"
mainwindow start
成功调用MainWindow中start内打印输出,则表明ctk插件接口正常定义并能成功加载。其中start(ctkPlugin::START_TRANSIENT)表示立即启用插件,不设置参数的话加载后也不会立即打印输出。
小结
如果出现"Failed to install plugin",那真是……太正常了。错误信息由ctkPluginException返回,观察e.getType()返回参数么。如果是0,则表示ctk框架没有识别到这个插件;检查加载路径是否正确,检查activator声明插件格式是否规范,检查activator-qrc-MANIFEST.MF逻辑是否正确。比较不友好的一点是,插件加载失败很少提示详细信息,对框架不熟悉的人需要花比较多的时间排查问题。
参考文献
ctk插件基本格式:http://blog.csdn.net/qq137921399/article/details/47039023
MENIFEST.MF文件:http://www.voidcn.com/article/p-bclkrnrz-bqt.html