新浪微博
腾讯微博
会员列表
统计排行
基本信息
到访IP统计
管理团队
管理统计
在线会员
会员排行
版块排行
帖子排行
标签排行
帮助
下拉
用户名
电子邮箱
用户名
密 码
记住登录
登录
找回密码
注册
快捷通道
关闭
您还没有登录,快捷通道只有在登录后才能使用。
立即登录
还没有帐号? 赶紧
注册一个
首页
论坛
Qt下载
作品展
群组
个人中心
捐赠、管理与开发
邮件订阅
帖子
文章
日志
用户
版块
群组
帖子
搜索
QTCN开发网
>
Qt基础编程
>
Creating Plugins (二)
发帖
回复
返回列表
新帖
6436
阅读
1
回复
[共享]
Creating Plugins (二)
[复制链接]
上一主题
下一主题
离线
escene
UID:80286
注册时间
2009-06-04
最后登录
2017-09-14
在线时间
79小时
发帖
31
搜Ta的帖子
精华
0
金钱
310
威望
41
贡献值
0
好评度
31
访问TA的空间
加好友
用道具
新手上路
关闭
个人中心可以申请新版勋章哦
立即申请
知道了
加关注
发消息
只看楼主
倒序阅读
楼主
发表于: 2011-05-15
接前面的
Qt插件学习(一)
,继续学习
插件
的 lower level api这次,直接写个小例子吧:
接口
程序要能感知插件,需要程序和插件共同遵守某种规则。于是定义一个共同的接口[pre]
//mathinterface.h
#include <QtCore/QtPlugin>
class MathInterface
{
public:
virtual ~MathInterface() {}
virtual int math(int v) = 0;
};
Q_DECLARE_INTERFACE(MathInterface, "com.example.Plugin.MathInterface/0.1");[/pre]这儿用到的这个宏的定义在
qobject
.h中:[pre]#define Q_DECLARE_INTERFACE(IFace, IId) \
template <> inline const char *qobject_interface_iid<IFace *>() \
{ return IId; } \
template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
{ return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
{ return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }[/pre]注意,这儿用到了 [pre]qt_metacast()[/pre]稍后会看到这个函数在何处被定义。
使用插件
[pre]//main.cpp
#include <QtCore>
#include "mathinterface.h"
int main(int argv, char *args[])
{
QCoreApplication app(argv, args);
QDir pluginsDir(qApp->applicationDirPath());
foreach (
QString
fileName, pluginsDir.entryList(QDir::Files)) {
QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
if (plugin) {
MathInterface *interface = qobject_cast<MathInterface *>(plugin);
if (interface) {
qDebug()<<interface->math(10);
}
}
}
return app.exec();
}[/pre]遍历一个路径(比如这儿的可
执行
程序所在
目录
),依次用 QPluginLoader 进行加载,如果加载成功且转换成接口指针成功,则调用接口的函数。
这儿用了一个 qobject_cast 进行类型转换。是不是很神奇:这儿转换的类型不是我们一直坚信的 QObject 或其子类。这用的是我们接口定义时的宏。
插件定义
头文件
[pre]//plugin1.h
#include <QtCore/QObject>
#include "mathinterface.h"
class Plugin1:public QObject, public MathInterface
{
Q_OBJECT
Q_INTERFACES(MathInterface)
public:
Plugin1(QObject *parent=NULL);
int math(int v);
};[/pre]cpp文件
[pre]//plugin1.cpp
#include "plugin1.h"
Plugin1::Plugin1(QObject *parent)
:QObject(parent)
{
}
int Plugin1::math(int v)
{
return 100*v;
}
Q_EXPORT_PLUGIN2(plugin1, Plugin1);[/pre]这儿出现的新的宏是:Q_INTERFACES(MathInterface)
这是个
moc
处理的宏,moc的结果中包含下面的代码:
[pre]void *Plugin1::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Plugin1))
return static_cast<void*>(const_cast< Plugin1*>(this));
if (!strcmp(_clname, "MathInterface"))
return static_cast< MathInterface*>(const_cast< Plugin1*>(this));
if (!strcmp(_clname, "com.example.Plugin.MathInterface/0.1"))
return static_cast< MathInterface*>(const_cast< Plugin1*>(this));
return QObject::qt_metacast(_clname);
}[/pre]从这儿可以看出前面的qobject_cast是如何通过调用qt_metacast来起作用的。
pro
文件
为了完整,看一下程序和插件分别对应的pro文件
project.pro
app/
app.pro
main.cpp
mathinterface.h
plugin1/
plugin1.pro
plugin1.h
plugin1.cpp
[pre]#app.pro
HEADERS = mathinterface.h
SOURCES = main.cpp
CONFIG += console
TARGET = main
DESTDIR = ../[/pre]
[pre]#plugin1.pro
TEMPLATE = lib
CONFIG += plugin
INCLUDEPATH += ../app
HEADERS = plugin1.h
SOURCES = plugin1.cpp
DESTDIR = ../[/pre]其实Qt自带的Manual和例子讲得很清楚了,本文中不过提了一点用得到宏是如何工作的。
QPluginLoader
使用插件是通过QPluginLoader来完成的。
回想上一篇中提到
Q_EXPORT_PLUGIN2(PluginName, ClassName)
展开后的两个函数:
[pre]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;
}[/pre]QPluginLoader 正是借助这两个接口函数,来判断我们的插件是否有效的。看一下
load
的源码:
这儿的d是 QLibraryPrivate 的实例
[pre]bool QPluginLoader::load()
{
if (!d || d->fileName.isEmpty())
return false;
if (did_load)
return d->pHnd && d->instance;
if (!d->isPlugin())
return false;
did_load = true;
return d->loadPlugin();
}
[/pre]两个接口函数是分别在 d->isPlugin() 和 d->loadPlugin() 中被使用的。
参考
http://doc.qt.nokia.com/4.7/tools-echoplugin.html
http://doc.qt.nokia.com/4.7/plugins-howto.html
http://doc.qt.nokia.com/4.7/qpluginloader.html
共
条评分
回复
举报
分享到
淘江湖
新浪
QQ微博
QQ空间
开心
人人
豆瓣
网易微博
百度
鲜果
白社会
飞信
离线
ppdayz
UID:113403
注册时间
2011-03-14
最后登录
2016-07-29
在线时间
1377小时
发帖
781
搜Ta的帖子
精华
2
金钱
7965
威望
755
贡献值
0
好评度
746
访问TA的空间
加好友
用道具
禁止发言
加关注
发消息
只看该作者
1楼
发表于: 2011-05-15
楼主可以把原帖地址贴出来的,转载欢迎,但是个人觉得还是要尊重下原作者(不是我。。。)
共
条评分
回复
举报
发帖
回复
返回列表
http://www.qtcn.org/bbs
访问内容超出本站范围,不能确定是否安全
继续访问
取消访问
快速回复
限100 字节
您目前还是游客,请
登录
或
注册
进入高级模式
文字颜色
发 布
回复后跳转到最后一页
上一个
下一个
关闭
补充发布信息
验证码:
发 布
隐藏
快速跳转
站务及资讯
网站公告
新闻资讯
Qt官方发布
网站管理
Qt应用及资源
Qt 作品展
Qt代码秀
Qt应用版
Qt技术讨论区
Qt安装与发布
Qt中文处理
Qt基础编程
Qt QML开发
Qt嵌入式开发
Qt移动平台开发
其它技术开发讨论区
Qt图书专区
《C++ GUI Qt 4编程》(第2版)专栏
《Qt高级编程》专栏
《零基础学Qt4编程》专栏
《Qt设计模式》(第2版) 图书专栏
Python Qt GUI快速编程
Qt项目开发区
天池项目
Qt开放平台开发库
机械CAD
扇贝词典
非活跃项目区
社区中心
帖子回收站(Trash)
招聘、求职、供求、广告等
休闲娱乐
关闭
关闭
选中
1
篇
全选