插件是什么

  • 注意:这儿暂时不考虑静态插件(潜意识中总觉得它根本就不算插件)。

插件是一个动态库(共享库)。动态库是一个独立的文件中的独立模块,可被多个程序访问。

先看动态库的两种用法

1. 程序链接时指明动态库

这时程序中包含相应的头文件,编译时指定头文件路径,对于qmake来说:

LIBS += -L/path1/path2/.../ -labcd
INCLUDEPATH += /p1/p2/.../

这样一来,程序启动时会自动加载需要的链接库。

2. 程序中动态加载动态库

运行过程中找到来查找某个动态库,加载并解析出其中的某个函数。 Qt提供了QLibrary这个类来封装各个平台下的差异。

插件是提供特定接口的动态库

  • 它是动态库
  • 它需要一个或几个特定的接口(这样程序才能感知它)
  • 它采用第二种加载方式
  • Qt 为插件提供了 QPluginLoader,比通用 QLibrary 好用

Qt插件位置

动态加载,那么程序怎么知道去哪儿加载插件呢?

很多人抱怨,装有Qt的机器上一切正常,发布后,jpeg等格式图片看不成,数据库无法连接,汉字乱码...

其实答案很简单:

QCoreApplication 的 libraryPaths() 中有一些路径,比如:

  • $QTDIR/plugins
  • 可执行程序所在文件夹

然后程序启动后,会去这些路径下的下列子目录

  • imagesformats

    中 找图片插件

    sqldrivers

    中 找数据库驱动插件

    codecs

    中 找字符的编解码插件

    ...

这就是为什么:将 jpeg4.dll 放到可执行程序所在文件夹的 imagesformats 中即可解决问题的原因。

除此之外,要设置插件路径,我们还可以修改:

QCoreApplication::libraryPaths()

通过 addLibraryPath()

QLibraryInfo::location(QLibraryInfo::PluginsPath)

通过 qt.conf 文件

QT_PLUGIN_PATH

环境变量

Manual 中对此有详细介绍。有关插件路径问题,请考虑 http://blog.csdn.net/dbzhang800/archive/2011/06/14/6543489.aspx

插件API

Qt 提供了两个层次的Api

Higher-level

用于扩展Qt自身的工程,比如前述的图片插件、编解码插件等等
前面的插件位置提到的主要是这个

Lower-level

用于扩展 应用程序的功能,比如 QtCreator 本身用了非常多的专有插件

higher-level

这部分,插件本身的api很简单,困难在功能实现上。比如实现一个 style 插件:

  • 派生 QStyle 或它的子类,实现自己的 Style 类(难点)
  • 派生 QStylePlugin,实现插件,在它内部创建 Style 的对象

这两个都没什么好说的,只是一个宏特别关键:

Q_EXPORT_PLUGIN2(PluginName, ClassName)

看它的源代码,也是一堆宏,贴出来也不好看

# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
Q_PLUGIN_VERIFICATION_DATA \
Q_EXTERN_C Q_DECL_EXPORT \
const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \
{ return qt_plugin_verification_data; } \
Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \
Q_PLUGIN_INSTANCE(PLUGINCLASS)

展开看一下:

static const char qt_plugin_verification_data[] = \
"pattern=QT_PLUGIN_VERIFICATION_DATA\n" \
"version=4.7.0\ndebug=false\nbuildkey=xxx";

extern "C" Q_DECL_EXPORT const char * qt_plugin_query_verification_data()
{
return qt_plugin_verification_data;
}

extern "C" Q_DECL_EXPORT qt_plugin_instance()
{
static QPointer<QObject> _instance;
if (!_instance)
_instance = new ClassName;
return _instance;
}

这样一来舒服多了,导出了两个函数:

  • 一个返回值是一个长长的字符串,用来校验差价和程序所用Qt版本什么的是否匹配
  • 另一个返回的是插件类的对象,这样通过该函数就可以使用插件了。

lower-level

这一部分和本文其他部分关系不是太紧密,而且内容可能比较多,还是单独出来准备"插件学习二"吧。

  • 不像图片插件、数据库插件等,Qt为他们提供了现成的接口。这儿我们必须实现自己的接口(别人也不清楚我们的需求,对吧)

静态插件

  • 这个东西怎么说呢,尽管静态编译过Qt,但基本没用过。所以在这静态插件上面应该更没有什么发言权。
  • 熟悉Qt静态编译的,应该对此更熟一些,因为这是插件都是静态的。

静态插件使用

这时它是一个静态库。静态库如何使用?不用多说了,肯定直接链接到程序中。于是我们需要:

  • 包含头文件
  • 指定链接库

对与Qt提供的 higher-level 插件,比如图片插件 jpeg,这意味着:

代码中,(使用宏,也就是使动态编译时它不起作用)

  • #include<QtPlugin>

  • Q_IMPORT_PLUGIN(qjpeg)

pro文件内,(指定要链接的库)

  • QTPLUGIN += qjpeg

静态插件用到的宏

当静态编译时,插件中的宏

Q_EXPORT_PLUGIN2(PLUGINNAME, ClassName)

展开为

qt_plugin_instance_PLUGINNAME()
{
static QPointer<QObject> _instance;
if (!_instance)
_instance = new ClassName;
return _instance;
}

同时,工程中的宏

Q_IMPORT_PLUGIN(PluginName)

展开为:

QObject *qt_plugin_instance_PLUGINNAME();
class StaticPLUGINNAMEPluginInstance
{
public:
StaticPLUGINNAMEPluginInstance() 
{
qRegisterStaticPluginInstanceFunction(qt_plugin_instance_PLUGINNAME);
}
};
static StaticPLUGINNAMEPluginInstance staticPLUGINNAMEInstance;

这也很容易理解,Q_EXPORT_PLUGIN2(PLUGINNAME, ClassName) 中的第一个参数做什么用了。

参考

  • http://doc.qt.nokia.com/4.7/plugins-howto.html

  • http://doc.qt.nokia.com/4.7/deployment-plugins.html

转载于:https://www.cnblogs.com/lvdongjie/p/3758094.html

Qt 插件学习(一)相关推荐

  1. 我的QT Creator学习笔记(二十一)——Qt国际化和Qt插件

    参考文献:<Qt Creator 快速入门>第三版 霍亚飞编著 一.国际化 Qt可以使用Qt Linguist工具完成应用程序的翻译工作,生成.qm文件,然后在不同情况下为应用程序安装不同 ...

  2. Qt值得学习吗?详解Qt的几种开发方式

    qt值得学习吗? 嵌入式要学的东西真的很多,我们可能会说不写界面的话就不用学qt了?我不赞同. Qt的实现主要是采用p-impl手法,实现接口与实现分离,它有很好的消息循环机制,有的对象与线程的相关性 ...

  3. QT开发学习-第一章-QT简介

    QT简介 一.QT简介 1.QT简介 2.QT优点 二.QT开发工具 1.Qt Creator 2.Qt Designer 3.Qt Linguist 4.Qt Assistant 5.Qmake 6 ...

  4. BestMPRBaseVtk-001-第一个Qt插件、建立子项目工程、建立插件子项目、建立测试项目

    ​ 是的,你没有看错,我膨胀了,我已经不满足于在Qt中使用那种控件提升为的方法了,现在我要把VTK的一些并能封装成一个控件.这样可以让前端的逻辑控制更加关注逻辑,而我可以借此机会好好的学习一下VKT和 ...

  5. 收藏的博客 -- Qt/C++学习

    Qt Creator环境: 使用Qt Creator作为Linux IDE,代替Vim:实现两台Linux电脑远程部署和调试(一台电脑有桌面系统,一台电脑无桌面系统) 使用Qt Creator作为Li ...

  6. jquery插件学习(六)

    继续上面的示例说明 把其中的参数默认值作为$.fn.color对象的属性单独进行设计,然后借助jquery.extend方法,覆盖原来的参数选项即可 ;(function($){$.extend($. ...

  7. vs2010 Qt插件报错Couldn't register all Qt4VSAddin command解决方案

    打开vs2010,也不存在qt插件: 1.更新你的VS2010到sp1: 2.cmd执行以下命令:(是一个命令,注意32位或者64位路经可能不同确认2个路径的文件存在再执行,否则安装sdk.) win ...

  8. qt插件元数据不包含一个有效的元数据_Qt5个人软件插件使用(低级API)

    前言 今天想看一些Qt 插件系统.看了之后发现Qt支持两种插件方式:高级 API 和低级 API. 高级 API 指的的为Qt软件本身定制插件: 低级 API 指的是为自己写的软件定制插件. 这篇文章 ...

  9. qt插件元数据不包含一个有效的元数据_qt creator源码全方面分析(2-10-2)

    Creating Your First Plugin 本节介绍,如何使用Qt Creator提供的插件模板,来创建Qt Creator插件,并获取对插件的组成和结构的第一印象. 创建一个插件项目 Qt ...

最新文章

  1. 多维数组与指针之间的关系详解
  2. android 输入锁屏密码错误,安卓系统手机锁屏密码输错被停用了如何解决
  3. Fast Flux技术——本质就是跳板,控制多个机器,同一域名指向极多的IP(TTL修改为0),以逃避追踪...
  4. 使用 IIS 在 Windows 上托管 ASP.NET Core2.0
  5. 某个知名技术论坛用户名和密码泄露(第一部分)
  6. 【debug】UnicodeDecodeError: codec can't decode byte 0xbd in position 4: invalid start byte
  7. 超Mask RCNN速度4倍,仅在单个GPU训练的实时实例分割算法
  8. 21. GD32F103C8T6入门教程-flash/fmc连续读写操作
  9. Python+django网页设计入门(16):优化设计复用分页代码
  10. Unable to add window -- token android.os.BinderProxy---Android原生开发工作笔记142
  11. 时隔两年,PuTTY 喜提新版
  12. Postgre使用笔记之按id顺序排序意义
  13. android wps页面设置,WPS中设置纸张的方法
  14. 官方解决方案:WPS for Mac 云字体删除的问题,Mac版WPS已下载云字体无法删除的问题
  15. python少儿编程竞赛_家长必读!国内外含金量最高的编程比赛全在这了!
  16. python常用颜色表示_Python命令行的常用颜色,python,字体
  17. 小米手机打开报告mimu查看程序调试错误locat
  18. 结构化数据、半结构化数据和非结构化数据分析
  19. 聚名:怎样批量查询50个域名的注册信息?
  20. 使用 ROT13 算法加密解密数据

热门文章

  1. c语言用指针访问简单变量,关于C语言指针,个人认为最经典、最简单的一个应用...
  2. 使用物理硬盘_许迎果 第147期 机械硬盘的物理结构和逻辑结构
  3. 谈谈未来简书首页拒稿界面的设计思路
  4. Arcgis Javascript那些事儿(十一)--网络分析服务使用
  5. ArcGIS Maritime 发布海图切片服务详解
  6. Sublime Text 教程
  7. DXUT框架剖析(6)
  8. summernote 不能上传图片_Typora自定义命令自动上传图片
  9. 天津工业大学19年计算机考研大纲,天津工业大学2019考研《计算机原理及接口技术》复试大纲...
  10. Java复习总结(一)思维导图