您的位置:首页 > 编程语言 > Qt开发

Qt插件机制的学习

2013-04-26 22:31 369 查看


Mesh Deformer的架 构若想参照OpenFlipper来实现,首先需要了解Qt plugin system的结构以及如何编写qt plugins.

以下摘抄了Qt文档中的部分内容(只与自己想要实现的功能相关的内容)


The Lower-Level API: Extending Qt Applications

Not only Qt itself but also Qt application can be extended through plugins. This requires the application to detect and load plugins using QPluginLoader.
In that context, plugins may provide arbitrary functionality and are not limited to database drivers, image formats, text codecs, styles, and the other types of plugin that extend Qt's functionality.

Making an application extensible through plugins involves the following steps:

Define a set of interfaces (classes with only pure virtual functions) used to talk to the plugins.
Use the Q_DECLARE_INTERFACE() macro to tell Qt's meta-object
system about the interface.
Use QPluginLoader in the application to load the plugins.
Use qobject_cast() to test whether a plugin implements a given interface.

Writing a plugin involves these steps:

Declare a plugin class that inherits from QObject and from the interfaces that the plugin wants to provide.
Use the Q_INTERFACES() macro to tell Qt's meta-object
system about the interfaces.
Export the plugin using the Q_EXPORT_PLUGIN2() macro.
Build the plugin using a suitable .pro file

Qt的插件机制可以用来动态地添加功能,而这个扩展通过接口来实现。具体的包括两个方面,一个是插件本身需要对外声称自己提供哪些功能,另一方面是在调用插件的部分(主程序)需要知道如何导入插件。

我参照Qt文档写了如下的测试程序:

(首先,是接口的代码,利用Q_DECLARE_INTERFACe来声明提供接口的类型)

[cpp] view
plaincopy

#ifndef TESTINTERFACE_H

#define TESTINTERFACE_H

#include <QtPlugin>

class TestInterface{

public:

virtual ~TestInterface(){}

virtual QString name() const = 0;

};

Q_DECLARE_INTERFACE(TestInterface,"meshdeformer.TestInterface")

#endif

插件,实现接口特定的功能

[cpp] view
plaincopy

////////////TestPlugin.h///////////////

#ifndef TESTPLUGIN_H

#define TESTPLUGIN_H

#include "TestInterface.h"

#include <QObject>

#include <QtPlugin>

class TestPlugin : public QObject,public TestInterface{

Q_OBJECT

Q_INTERFACES(TestInterface)

public:

TestPlugin(){}

virtual ~TestPlugin(){}

public:

QString name() const

{

return QString("TestPlugin");

}

};

#endif

[cpp] view
plaincopy

///////////TestPlugin.cc////////////

#include "TestPlugin.h"

//Important, this should be place in CPP file

Q_EXPORT_PLUGIN2(test_plugin,TestPlugin);

需要注意的是,插件向外声明提供接口的宏Q_EXPORT_PLUGIN2需放在CPP文件中,不然链接的时候会出现多个link的情况。

而且,这里面的第一个参数为实例的名称,就与QMAKE或CMAKE的产生的目标的名称一致。即此处的test_plugin应与下面CMAKELISTS中的add_library中生成的目标一致。

在这个目录下相对应的CMakeLists.txt如下:

[cpp] view
plaincopy

project(PluginTest)

cmake_minimum_required(VERSION 2.6)

find_package(Qt4 REQUIRED)

include(${QT_USE_FILE})

qt4_wrap_cpp(TestPlugin_MOC TestPlugin.h)

# a plugin is a shared library, but build in a certain environment

add_definitions(${QT_DEFINITIONS})

add_definitions(-DQT_PLUGIN)

add_definitions(-DQT_SHARED)

add_definitions(-DQT_NO_DEBUG)

add_library(test_plugin SHARED TestPlugin.cc ${TestPlugin_MOC})

target_link_libraries(test_plugin ${QT_LIBRARIES})

插件实际上看作是shared library的形式。

另外,在主程序那一方,通过导入(windows下为dll,linux下为so,mac下为.dylib)的形式来为主程序添加新的功能

主程序如下:

[cpp] view
plaincopy

#include <QCoreApplication>

#include <QDir>

#include <QPluginLoader>

#include "TestPlugin.h"

int main(int argc,char** argv)

{

QCoreApplication* app = new QCoreApplication(argc,argv);

TestInterface* interface = 0;

//Load plugins

QDir pluginsDir(qApp->applicationDirPath());

pluginsDir.cd("TestPlugin");

foreach(QString fileName,pluginsDir.entryList(QDir::Files)){

QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));

QObject* plugin = pluginLoader.instance();

if(plugin){

interface = qobject_cast<TestInterface*>(plugin);

if(interface){

printf("plugin load ok/n");

}

else{

printf("plugin not load./n");

}

}

}

return app->exec();

}

相对应的cmake文件如下:

[cpp] view
plaincopy

project(QtPluginTest)

cmake_minimum_required(VERSION 2.6)

find_package(Qt4 REQUIRED)

include(${QT_USE_FILE})

add_subdirectory(TestPlugin)

include_directories(TestPlugin)

link_directories(TestPlugin)

add_executable(test main.cpp)

target_link_libraries(test ${QT_LIBRARIES})

本来Qt的plugins有特定的存放目录(plugins),但这里纯粹为测试能否正确载入,所以在实现文件中hard code了。

测试:

在该目录下用以下命令测试:

mkdir build

cd build

cmake ..

make

./test

运行后会打印一个“导入成功”的提示。

源代码下载地址: http://download.csdn.net/source/2314773
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: