Qt插件机制的学习
发布日期:2021-10-03 22:59:36 浏览次数:16 分类:技术文章

本文共 3841 字,大约阅读时间需要 12 分钟。

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 . 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:

  1. Define a set of interfaces (classes with only pure virtual functions) used to talk to the plugins.
  2. Use the () macro to tell Qt's  about the interface.
  3. Use  in the application to load the plugins.
  4. Use () to test whether a plugin implements a given interface.

Writing a plugin involves these steps:

  1. Declare a plugin class that inherits from  and from the interfaces that the plugin wants to provide.
  2. Use the () macro to tell Qt's  about the interfaces.
  3. Export the plugin using the () macro.
  4. Build the plugin using a suitable .pro file

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

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

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

[cpp] 
  1. #ifndef TESTINTERFACE_H  
  2. #define TESTINTERFACE_H  
  3. #include <QtPlugin>  
  4. class TestInterface{  
  5.  public:  
  6.   virtual ~TestInterface(){}  
  7.   virtual QString name() const = 0;  
  8. };  
  9. Q_DECLARE_INTERFACE(TestInterface,"meshdeformer.TestInterface")  
  10. #endif  
 

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

[cpp] 
  1. TestPlugin.h///  
  2. #ifndef TESTPLUGIN_H  
  3. #define TESTPLUGIN_H  
  4. #include "TestInterface.h"  
  5. #include <QObject>  
  6. #include <QtPlugin>  
  7. class TestPlugin : public QObject,public TestInterface{  
  8.   Q_OBJECT  
  9.     Q_INTERFACES(TestInterface)  
  10. public:  
  11.   TestPlugin(){}  
  12.   virtual ~TestPlugin(){}    
  13. public:  
  14.   QString name() const  
  15.   {  
  16.     return QString("TestPlugin");  
  17.   }  
  18.     
  19. };  
  20. #endif  
 

 

[cpp] 
  1. ///TestPlugin.cc  
  2. #include "TestPlugin.h"  
  3. //Important, this should be place in CPP file  
  4. Q_EXPORT_PLUGIN2(test_plugin,TestPlugin);  
 

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

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

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

[cpp] 
  1. project(PluginTest)  
  2. cmake_minimum_required(VERSION 2.6)  
  3. find_package(Qt4 REQUIRED)  
  4. include(${QT_USE_FILE})  
  5. qt4_wrap_cpp(TestPlugin_MOC  TestPlugin.h)  
  6. # a plugin is a shared library, but build in a certain environment  
  7. add_definitions(${QT_DEFINITIONS})  
  8. add_definitions(-DQT_PLUGIN)  
  9. add_definitions(-DQT_SHARED)  
  10. add_definitions(-DQT_NO_DEBUG)  
  11. add_library(test_plugin SHARED TestPlugin.cc ${TestPlugin_MOC})  
  12. target_link_libraries(test_plugin ${QT_LIBRARIES})  
 

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

 

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

主程序如下:

[cpp] 
  1. #include <QCoreApplication>  
  2. #include <QDir>  
  3. #include <QPluginLoader>  
  4. #include "TestPlugin.h"  
  5. int main(int argc,char** argv)  
  6. {  
  7.   QCoreApplication* app = new QCoreApplication(argc,argv);  
  8.   TestInterface* interface = 0;  
  9.     
  10.   //Load plugins  
  11.   QDir pluginsDir(qApp->applicationDirPath());  
  12.   pluginsDir.cd("TestPlugin");  
  13.     
  14.   foreach(QString fileName,pluginsDir.entryList(QDir::Files)){  
  15.     QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));  
  16.     QObject* plugin = pluginLoader.instance();  
  17.     if(plugin){  
  18.       interface = qobject_cast<TestInterface*>(plugin);  
  19.       if(interface){  
  20.     printf("plugin load ok/n");  
  21.       }  
  22.       else{  
  23.     printf("plugin not load./n");  
  24.       }  
  25.     }      
  26.   }  
  27.   return app->exec();  
  28. }  
 

相对应的cmake文件如下:

[cpp] 
  1. project(QtPluginTest)  
  2. cmake_minimum_required(VERSION 2.6)  
  3. find_package(Qt4 REQUIRED)  
  4. include(${QT_USE_FILE})  
  5. add_subdirectory(TestPlugin)  
  6. include_directories(TestPlugin)  
  7. link_directories(TestPlugin)  
  8. add_executable(test main.cpp)  
  9. target_link_libraries(test ${QT_LIBRARIES})  
 

 

 

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

 

 

测试:

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

mkdir build

cd build

cmake ..

make

 

./test

 

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

 

 

源代码下载地址: 

转载地址:https://blog.csdn.net/lclflash/article/details/8856779 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:轻量级C++插件框架 x3py 可以用了
下一篇:Qt 插件学习(二)

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2023年03月04日 11时51分52秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

最新文章

c语言 java转换器,求助大神!!!JAVA转换成C语言 2019-12-06 20:23:43
linux c++ for i<0 循环,C++ for循环 2019-12-06 20:23:43
c语言调用串口扫码枪,C#利用控件mscomm32.ocx读取串口datalogic扫描枪数据 2019-12-06 20:23:43
labview c语言定义变量,第一章:LabVIEW 的编程环境 如何使用 VI 的重入属性(Reentrant)... 2019-12-06 20:23:44
linux编译安装openssh,RHEL6编译安装OpenSSH 2019-12-06 20:23:41
linux看安装了哪些函数,如何查看linux动态库中包含哪些函数 2019-12-06 20:23:42
allegro linux 安装教程,Linux上Centos系统知识图谱Allegrograph 6.6.0的安装方法和流程介绍... 2019-12-06 20:23:42
共创桌面linux,摒弃前嫌 KDE携手GNOME共创Linux桌面 2019-12-06 20:23:42
linux open函数功能,Linux系统文件I / O编程(1)--- open()和其他基本功能 2019-12-06 20:23:42
linux安装ruby环境 rvm,如何快速正确的安装 Ruby, Rails 运行环境 2019-12-06 20:23:42
宝塔Linux301重定向,宝塔面板如何设置301重定向(详细教程)! 2019-12-06 20:23:42
oracle 连接失去联系,插入大文件时c# – “ORA-03135:连接失去联系” 2019-12-06 20:23:40
linux服务器重启查询命令行,last命令查看系统重启状态(人工手动重启的还是系统内用命令重启的系统)... 2019-12-06 20:23:41
linux中kvm配置文件,如何在linux中通过kvm安装虚拟机 2019-12-06 20:23:41
linux内核5.6,在Deepin V20下可用命令来升级Linux内核到5.6版本以上 2019-12-06 20:23:41
linux svn服务器搭建 jb51,详解Linux服务器配置——搭建SVN服务器 2019-12-06 20:23:41
php处理 xss方法,php实现XSS安全过滤的方法 2019-12-06 20:23:39
oracle 查询最高分,SQL查找一个表里,每个班级的最高分。 2019-12-06 20:23:40
oracle 中rank(),sql – 在oracle中RANK()和DENSE_RANK()函数之间有什么区别? 2019-12-06 20:23:40
oracle客户端连接阻塞,java – Oracle JDBC间歇性连接问题 2019-12-06 20:23:40