Qt plugin系统的几点说明
对于一个大型软件系统来说,实现plugin是一件很美妙的事情,一个成功的plugin系统可以使软件增色不少。Plugin最大的功能是在一定程度内提高了软件的灵活度和可扩展性。一个设计精良的server软件plugin系统甚至在server程序不退出的情况下可以调用新加入的plugin,实现不间断服务的升级。那么,Qt是怎样实现它的plugin系统呢?
使用Qt创建plugin和在程序中调用plugin是很简单的事情,Qt提供了很多helper class供大家使用。总体来说,Qt的plugin分为2种,按照Qt文档的说法,一种是高等级的plugin。其实说白了就是已经确定interface的Qt本身的plugin。(大家可能都知道,Qt的很多功能,像数据库驱动、图片格式支持、文字内码等都是通过plugin实现的)举个例子来说,Qt可能本身没有西班牙语(希望这次西班牙夺冠:-)的文字内码,但是程序员可以通过按照codec interface写出西班牙语的codec plugin从而使Qt支持西班牙语。
另一种是低等级的plugin。就是该plugin的interface也需要程序员自己编写。所以如果你知道怎么写一个低等级的plugin并使用它之后,高等级的plugin也就完全掌握了。下面我就重点说说低等级的plugin在Qt里实现的一些要点。
从编程的角度,重点还是OOP。所谓的plugin,其实就是一些按照特定interface写成的子类。该Interface必须是虚基类,且所有函数(除了析构)都是虚函数。而所谓的plugin就是继承该虚基类和QObject的子类。当程序调用该plugin的某个函数时,是通过该plugin的虚基类在运行时动态绑定至子类的vtable执行的。所以Qt实现plugin的基础还是OOP的继承和多态。
举个大家都知道的例子来说明,PhotoShop(可能它并不是这么实现的)的所有滤镜有个统一的interface虚基类,该类提供了一个虚函数doSomeWork用于实现滤镜效果。当用户选择某个特殊滤镜时,程序会调用plugin中该滤镜class的doSomeWork实现函数来执行该操作,从而实现特定的滤镜功能。
那么为什么该plugin类不但要继承interface类,还需要继承QObject类呢?原因是调用plugin时需要该plugin类QObject那部分的meta信息。如果大家看过例子代码,会发现,用QPluginLoader调用plugin的文件后,关键的一步是确定该plugin是什么类型的。简单的另人惊讶,一句qobject_cast就搞定了。刚看到这句我百思不得其解,好在Qt有源代码可看,看了源代码发现qobject_cast类似于标准C++的dynamic_cast,且无需RTTI支持并能跨DLL。在代码中,qobject_cast是通过QObject的metaobject的cast函数来实现的。那么该函数是怎么写的呢?
/*!
/internal
Returns /a obj if object /a obj inherits from this
meta-object; otherwise returns 0.
*/
QObject *QMetaObject::cast(QObject *obj) const
{
if (obj) {
const QMetaObject *m = obj->metaObject();
do {
if (m == this)
return const_cast<QObject*>(obj);
} while ((m = m->d.superdata));
}
return 0;
}
从子类的metaobject开始查找,一直向父类循环,直至找到一致的meta(类信息)。所以,qobject_cast其实是确定该类是否是指定父类的派生类,如果是的话得到其指针。也就是说确定一个plugin是什么类型是通过继承关系来实现的。
从文件的角度来说,一个或多个plugin可以生存在同一个动态库里,windows下是dll。那么,这个dll怎么能动态的将plugin暴露给调用者呢?最关键的是Q_EXPORT_PLUGIN2这个宏。Qt文档特意说明,同一个plugin必须且只能调用它一次,且必须在实现文件的末尾。为什么呢?
因为这个宏最终调用了另一个宏,Q_PLUGIN_INSTANCE,而它的定义如下:
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) /
{ /
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; /
if (!_instance) /
_instance = new IMPLEMENTATION; /
return _instance; /
}
不知道大家有没有注意到static并且让design pattern中某个可爱的模式掠过你的脑海。从这个角度上说,你最适合在plugin中完成的代码是那些事务性的代码,即使用调用者的资源完成某些计算或操作。当你想在plugin中分配大量资源和组织一个庞大的类战队时,请三思。
其它的一些细节如pro文件怎么配置,plugin文件的目录等等是一些细节问题,大家可以看文档解决。
不知我写的是不是太少且太跳跃了。我觉得大家水平都很高,一些简单的细节问题就不在费时费力描述了。只把自己认为有点意思和重要的信息写出来。TX们有兴趣的话也可以写些东西互相交流,毕竟Qt的中文资料太少了。
最后,关于最近比较火爆的皇帝唐的事情,我也有一些想法。不过我这个博主要是技术文章,所以我只说一句和大家共勉。“诚信比金子更可贵”
http://blog.csdn.net/superjoel/article/details/5725209
Qt plugin系统的几点说明的更多相关文章
- 深度探索QT窗口系统(五篇)
窗口作为界面编程中最重要的部分,没有窗口就没有界面,是窗口让我们摆脱了DOS时代,按钮是一个窗口,文本框是一个窗口,标签页是一个窗口,...一个窗口可以由多个窗口组成,每天我们都在与窗口打交道,当你打 ...
- 界面编程之QT窗口系统20180726
/*******************************************************************************************/ 一.坐标系统 ...
- Qt 学习之路 2(24):Qt 绘制系统简介
Qt 学习之路 2(24):Qt 绘制系统简介 豆子 2012年10月30日 Qt 学习之路 2 77条评论 Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于Q ...
- Qt Resource系统概说(资源压缩不压缩都可以)
什么是Qt Resource系统?简单的说,就是在可执行程序中存储binary文件,而且还是与平台无关的. 与Qt Resource系统密切相关的有三个法宝,分别是qmake.rcc.QFile. q ...
- Qt坐标转换系统的理解
转 https://blog.csdn.net/hgcprg/article/details/53537106 今天又看了一篇对Qt坐标转换系统以及QTransform的博客,作者讲的非常透彻,链接如 ...
- Qt:Qt资源系统
学习自 Qt 资源系统(Qt Resource System) - 知乎 1.什么是Qt 资源系统 Qt资源系统是一种将图片.数据存储于二进制文件中的一套系统.这些图片.数据会被我们的程序使用,它们称 ...
- Qt插件系统
说明 近期入职新公司,新公司的项目用到了Qt的插件系统,花时间了解了一下,还以为Qt的插件系统有多么高级呢,原来归根到底还是 dll 的动态调用时获取其中的类那一招啊,原理和之前的文章<DLL的 ...
- 关于QT的系统总结
编译环境与开发流程 开发QT有两种IDE可以使用,一种是使用 VS + Qt 的插件,另一种就是使用QtCreator工具.前一种是微软的工具,用的都比较多容易上手,缺点是信号槽的支持不太好,需要手写 ...
- Qt设置系统时间(使用SetSystemTime API函数)
大家都知道Qt中有QDateTime等有关时间与日期的类,类中包含很多成员函数,可以很方便的实现有关时间与日期的操作,比如:想要获得系统当前的时间与日期,可以调用currentDateTime(); ...
随机推荐
- 使用java API查询java类
一.java API的下载地址 前面列举了常用的java类,但只是介绍了功能,具体详细的用法(比如要知道该类的属性和方法)要需要调用java的API(Application Program Inter ...
- jquery $.ajax $.get $.post的区别
$.ajax 是 jQuery 底层 AJAX 实现,$.ajax是一种通用的底层封装,$.ajax()请求数据之后,则需要使用回调函数,有beforeSend.error.dataFilter.su ...
- web浏览器中的javascript 1
Html 文档嵌入客户端有4种方式. 1. 内联.放置在<script>和</script>标签对之间. 2.放置在<script>标签的src属性指定的外部文件中 ...
- CSS换行2
1.可以使用强制换行符号<br />换行.如果在一个文章里可以在文章需要换行的地方加入<br />即可实现自动换行-常说的小换行,与换行前没有间隔.实例如下图 换行说明图无间隔 ...
- 简单天气应用开发——自定义TableView
顺利解析JSON数据后,天气数据已经可以随意提取了,现在要做的就是建立一个简单的UI. 实况信息较为简单,几个Lable就可以解决.主要是七天天气预报有点麻烦,那是一个由七个字典构成的数组,需要提取出 ...
- SQLite For .Net 已经整合了32位和64位
以前引用SQLite.DLL的时候,如果是winform等桌面程序,还要分32位和64位不一样的DLL,但最近已经整合为一个包了 打开vs的程序包管理器控制器,输入: install-package ...
- Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信
链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socke ...
- codeforces 451E. Devu and Flowers 容斥原理+lucas
题目链接 给n个盒子, 每个盒子里面有f[i]个小球, 然后一共可以取sum个小球.问有多少种取法, 同一个盒子里的小球相同, 不同盒子的不同. 首先我们知道, n个盒子放sum个小球的方式一共有C( ...
- selenium 学习笔记 ---新手学习记录(8) 问题总结(java)
1.获取执行js代码后的返回值 //获取滚动距离 String jl="return $('#chapterul li').height();"; Long jlhq=(Long) ...
- 用JS画斐波那契螺旋线(黄金螺旋线)
偶然看到斐波那契螺旋线(黄金螺旋线)的定义及画图方法,试着用JS画了一下,很漂亮,很好玩 具体定义及画法大家查一下就有了,很简单. 以下是代码: <!DOCTYPE html> <h ...