`
美丽的小岛
  • 浏览: 298856 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

[转—QT]moc生成文件分析

    博客分类:
  • QT
阅读更多

首先看一下简单含有的signal, slot代码

  1. class myClass : public QObject  
  2. {  
  3.     Q_OBJECT  
  4. public:  
  5.     myClass();  
  6.     ~myClass();  
  7.     void trigger();  
  8.     void trigger2();  
  9. signals:  
  10.         void signalFunc(double);  
  11.         int signalFunc2(charint);  
  12. protected slots:  
  13.         void slotFunc(double);  
  14.         int slotFunc2(char);  
  15. };  
  16. // 只是实例代码,用来生成moc_myClass  
  17. #include"myClass.h"  
  18. #include<iostream>  
  19. using std::cout;  
  20. using std::endl;  
  21. myClass::myClass()  
  22. {  
  23.     connect(this, SIGNAL(signalFunc),  
  24.             this, SLOT(slotFunc));  
  25.     connect(this, SIGNAL(signalFunc2),  
  26.             this, SLOT(slotFunc2));  
  27. }  
  28. myClass::~myClass()  
  29. {  
  30. }  
  31. void myClass::slotFunc(double d)  
  32. {  
  33.     cout << "slotFunc" << endl;  
  34. }  
  35. int myClass::slotFunc2(char c)  
  36. {  
  37.     cout << "slotFunc2" << endl;  
  38.     return c;  
  39. }  
  40. void myClass::trigger()  
  41. {  
  42. }  
  43. void myClass::trigger2()  
  44. {  
  45. }   

编译生成moc_myClass.cpp

 

  1. static const uint qt_meta_data_myClass[] = {  
  2.  // content:  
  3.        4,       // revision  
  4.        0,       // classname  
  5.        0,    0, // classinfo  
  6.        4,   14, // methods  
  7.        0,    0, // properties  
  8.        0,    0, // enums/sets  
  9.        0,    0, // constructors  
  10.        0,       // flags  
  11.        2,       // signalCount  
  12.  // signals: signature, parameters, type, tag, flags  
  13.        9,    8,    8,    8, 0x05,  
  14.       34,   32,   28,    8, 0x05,  
  15.  // slots: signature, parameters, type, tag, flags  
  16.       56,    8,    8,    8, 0x09,  
  17.       73,    8,   28,    8, 0x09,  
  18.        0        // eod  
  19. };  

 其中methods部分,4代表这个对象含有4个signal + slot, 14是基础数字,在moc代码里面也是硬编码,数一下content的个数,刚好是14,这个14其实就是个偏移量,偏移到signal的第一行

signal和slot的flag提供了一些属性,这个会在后面的QObject::connect讲到。

这里需要提出来一点是signal和slot的第一个数值,9, 34, 56, 73这几个,这个马上会讲到先提出来,留个印象

这里前14个数值是对应的QMetaObjectPrivate的值

 

  1. struct QMetaObjectPrivate  
  2. {  
  3.     int revision;  
  4.     int className;  
  5.     int classInfoCount, classInfoData;  
  6.     int methodCount, methodData;  
  7.     int propertyCount, propertyData;  
  8.     int enumeratorCount, enumeratorData;  
  9.     int constructorCount, constructorData; //since revision 2  
  10.     int flags; //since revision 3  
  11.     int signalCount; //since revision 4  
  12.     ...  
  13.     ...   
  14. }  

 接下来是

 

  1. static const char qt_meta_stringdata_myClass[] = {  
  2.     "myClass/0/0signalFunc(double)/0int/0,/0"  
  3.     "signalFunc2(char,int)/0slotFunc(double)/0"  
  4.     "slotFunc2(char)/0"  
  5. };  

 

 

从这个字符串里面,可以看到第一个值为这个类的类名(元对象可以不通过RTTI给出类名的原因就在这里)

在第一个/0后面会给出第一个signal的返回值类型,在这个例子中signalFunc没有返回值,所以没有任何内容,

在第二个/0后面会给出参数名,因为moc读取的是头文件,而我们在头文件中没定义参数名,所以为空

然后就是signal的名字和参数列表类型,这里需要注意的是,即使头文件给出了参数名,在这里也会被忽略掉,只提供类型

再下一个/0后面就是下一个函数的描述了,描述的方式跟前面是一样的。

刚刚提到的9, 34, 56, 73这几个数字,在这里是有用的,这几个数字,刚好是这个字符串对应的函数开头的部分。比如9,那我们在这个字符串中数9个字符,即signalFunc(double)这一段内容。

 

然后是源对象的数据定义:

 

  1. const QMetaObject myClass::staticMetaObject = {  
  2.     { &QObject::staticMetaObject, qt_meta_stringdata_myClass,  
  3.       qt_meta_data_myClass, 0 }  
  4. };  
  5. 可以看到源对象的数据定义为:  
  6.     struct { // private data  
  7.         const QMetaObject *superdata;  
  8.         const char *stringdata;  
  9.         const uint *data;  
  10.         const void *extradata;  
  11.     }  

 

 

这个名为staticMetaObject的对象是由Q_OBJECT引入的

第一个数据为父类名字, moc对于多继承的限制可能也在于此。

moc规定多继承的情况下,moc会假设第一个继承的类为QObject, 并且必须要保证在多继承中,只有唯一一个类是继承自QObject的。这样看上去,多余一个QObject继承的,第二个QObject根本没办法识别出来。

第二个数据就是上面的字符串数据

第三个也是上面的uint*数据。

这个源对象非常关键,后面的内容就靠他了。

  1. const QMetaObject &myClass::getStaticMetaObject() { return staticMetaObject; }  
  2. const QMetaObject *myClass::metaObject() const  
  3. {  
  4.     return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;  
  5. }  

 

这2个方法都是由Q_OBJECT引入的。目的是返回这个类的元对象

  1. void *myClass::qt_metacast(const char *_clname)  
  2. {  
  3.     if (!_clname) return 0;  
  4.     if (!strcmp(_clname, qt_meta_stringdata_myClass))  
  5.         return static_cast<void*>(const_cast< myClass*>(this));  
  6.     return QObject::qt_metacast(_clname);  
  7. }  

 

还是由Q_OBJECT引入的

 

当传入的字符串数据是当前这个类的话,就将this指针转换成void指针传给外界: 这个操作相当危险。

如果不是当前类的话,就调用父类的qt_metacast继续查询。

在这里,我的父类是QObject,所以自然就调用QObject::qt_metacase了

 

在看qt_metacall之前,先看下signal的定义。 额。。事实上signal不需要你自己定义,moc已经帮我们完成这点了。

具体内容如下:

 

  1. // SIGNAL 0  
  2. void myClass::signalFunc(double _t1)  
  3. {  
  4.     void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };  
  5.     QMetaObject::activate(this, &staticMetaObject, 0, _a);  
  6. }  

 我们看到他将所有的参数都转型成void*指针保存到 void *a的数组中,然后调用了

QMetaObject::activate(this, &staticMetaObject, 0, _a);

看到传入的参数为this, 源对象和参数

这个函数实际上就是触发消息的函数,在这里不过多关注他,有机会再写

 

最终,int myClass::qt_metacall(QMetaObject::Call _c, int _id, void **_a)

会被调用,用来处理对应的signal的消息

代码如下

 

  1. int myClass::qt_metacall(QMetaObject::Call _c, int _id, void **_a)  
  2. {  
  3.     _id = QObject::qt_metacall(_c, _id, _a);  
  4.     if (_id < 0)  
  5.         return _id;  
  6.     if (_c == QMetaObject::InvokeMetaMethod) {  
  7.         switch (_id) {  
  8.         case 0: signalFunc((*reinterpret_castdouble(*)>(_a[1]))); break;  
  9.         case 1: { int _r = signalFunc2((*reinterpret_castchar(*)>(_a[1])),(*reinterpret_castint(*)>(_a[2])));  
  10.             if (_a[0]) *reinterpret_castint*>(_a[0]) = _r; }  break;  
  11.         case 2: slotFunc((*reinterpret_castdouble(*)>(_a[1]))); break;  
  12.         case 3: { int _r = slotFunc2((*reinterpret_castchar(*)>(_a[1])));  
  13.             if (_a[0]) *reinterpret_castint*>(_a[0]) = _r; }  break;  
  14.         default: ;  
  15.         }  
  16.         _id -= 4;  
  17.     }  
  18.     return _id;  
  19. }  

这里可以注意下,有返回值和没有返回值的处理方法~

moc所作的这些工作,都是为了元对象能更好的工作而做的准备

分享到:
评论

相关推荐

    qtcreator生成工程文件 文件列表工具 v1.4(更新)

    由于qtcreator本身没有添加文件夹的功能,要是逐个添加,碰到文件夹较多的情况下十分不方便,此软件主要是生成工程文件(目录名).pro,修复之前版本存在的一些bug,进一步完善。 其主要内容大致如下: QT += core...

    qtcreator生成工程文件 文件列表工具

    由于qtcreator本身没有添加文件夹的功能,要么去linux下生成目录,要么逐个手动添加,十分受限,此软件主要是生成工程文件lastfilelist.pro 其主要内容大致如下: QT += core gui TARGET = targettest TEMPLATE = ...

    CppMocTest.7z

    最简单方便的方式就是继承QObject,并在类开头放置Q_OBJECT 这个宏,在预编译前moc 会自动扫描所有头文件,根据 signals 和 slot 关键字,提取信号与槽的所有及对应的信息索引,并为 signals 生成相对应的函数。...

    Qt将Sqlite中的数据导出为Excel

    Qt将Sqlite中的数据导出为Excel,支持自动判断行列,可在项目中直接使用

    QT4 HELLO源生代码初学者

    使用VC2008+qt4.8,创建第一个QT程序。 手动生成MOC文件。moc.exe FindDialog.h -o moc_FindDialog.cpp

    基于C++&QT的员工薪资分析系统.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    Qt操作excel文件,基于QAxObject的封装,适用windows系统.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    基于C++ &QT的学生选课系统.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    基于QT平台的手持媒体播放器项目实战

    Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许 组件编程。2008年,奇趣科技被诺基亚公司收购,QT也因此成为诺基亚旗下的编程语言工具。...

    基于Qt编写的音乐播放器,界面由QML编写,网络和文件由C++实现,能够搜索和播放在线歌曲。.zip

    Qt Meta-Object System(元对象系统)是Qt框架的一个重要特性,它引入了元对象编译器(moc),用于在编译时生成额外的代码以支持对象间通信、反射、动态属性绑定等高级功能。 Signal & Slot机制是Qt中实现对象间...

    毕设项目:基于QT+sqlite的网络文件分享系统.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    Qt编译过程出现错误process_begin: CreateProcess(NULL, rm -f debug/moc_predefs.h, …) failed的解决办法

    最近运行QtWindows版本,发现无法copy,动态库生成后没法放到指定的位置。目前尚未解决,先记录一下。有知道的朋友不妨留言告知,谢谢。 Makefile.Debug:168: recipe for target 'compiler_moc_predefs_clean' ...

    基于QT实现的地图导航系统(Dijkstra算法).zip

    Qt Meta-Object System(元对象系统)是Qt框架的一个重要特性,它引入了元对象编译器(moc),用于在编译时生成额外的代码以支持对象间通信、反射、动态属性绑定等高级功能。 Signal & Slot机制是Qt中实现对象间...

    C++课设:基于Qt+Tcp实现的文件传递系统(客户端+服务端).zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    程序设计作业: p2p聊天系统 qt写的界面 C++实现.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    毕业设计项目:校园导航系统 QT界面+TSP(模拟退火)+A star寻路+最少换乘+单车调度(最小费用最大流)等.zip

    构建项目时,MOC工具读取C++源文件,当它发现类的定义里有Q_OBJECT宏时,它就会为这个类生成另外一个包含有元对象支持代码的C++源文件,这个生成的源文件连同类的实现文件一起被编译和连接。 除了信号和槽机制外,...

    自己 在xp下使用qt creator的一些心得

    自己 在xp下使用qt creator的一些心得 关于调用 moc 程序处理 signal and slot机制,有时候 qmake 生成的 Makefile 文件并不调用moc来预处理,因此这个时候可以先删除 Makefile,然后再生成。

    qt-opensource-windows-x86-5.11.2.zip.005

    QT 5.11.2离线安装包文件有点大2.6G,应用最广泛的开发的跨平台C++图形用户界面应用程序开发框架。...Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))

    一个基于QT WebEngine和WebChannel的JS和QT通信例子.zip

    Qt Meta-Object System(元对象系统)是Qt框架的一个重要特性,它引入了元对象编译器(moc),用于在编译时生成额外的代码以支持对象间通信、反射、动态属性绑定等高级功能。 Signal & Slot机制是Qt中实现对象间...

    qt-opensource-windows-x86-5.11.2.zip.007

    QT 5.11.2离线安装包文件有点大2.6G,应用最广泛的开发的跨平台C++图形用户界面应用程序开发框架。...Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))

Global site tag (gtag.js) - Google Analytics