Qt Moc文件详解

  • Moc文件内容
    • 类原始代码
    • 生成后Moc文件解析

Moc文件内容

Moc 文件是Qt moc工具生成的实现文件,用于实现Qt的元对象系统

类原始代码

class ParseQObject : public QObject
{Q_OBJECTQ_PROPERTY(int prop1 READ prop1 WRITE setProp1)// 属性1
public:explicit ParseQObject(QObject *parent = nullptr);//can create instance constructor 1Q_INVOKABLE ParseQObject(int constructIntParam, QObject *constructParentParam = nullptr);
signals:void sig1();//信号1void sig2(int sigParam2int);//信号2void sig3(char sigParam3char, int sigParam3int);//信号3
public slots:void slot1();//槽1void slot2(int slotParam2);//槽2void slot3(char slotParam3char, int slotPram3int);//槽3public:Q_INVOKABLE void InvokeFunc();//invoke function 1Q_INVOKABLE int InvokeFuncWithReturn();//invoke func 2int prop1();void setProp1(int v);private:int prop_1;
};

生成后Moc文件解析

QT_BEGIN_MOC_NAMESPACE
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
struct qt_meta_stringdata_ParseQObject_t {QByteArrayData data[19];char stringdata0[203];
};
//QT_MOC_LITERAL宏展开
/*//前置宏定义
struct Q_CORE_EXPORT QArrayData
{QtPrivate::RefCount ref;int size;uint alloc : 31;uint capacityReserved : 1;qptrdiff offset; // in bytes from beginning of headervoid *data(){Q_ASSERT(size == 0|| offset < 0 || size_t(offset) >= sizeof(QArrayData));return reinterpret_cast<char *>(this) + offset;}
}
typedef QArrayData QByteArrayData;//qbytearry
#define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }#define Q_REFCOUNT_INITIALIZE_STATIC { Q_BASIC_ATOMIC_INITIALIZER(-1) }#define Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \{ Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } #define Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \Q_STATIC_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset)/
#define QT_MOC_LITERAL(idx, ofs, len) \Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \qptrdiff(offsetof(qt_meta_stringdata_ParseQObject_t, stringdata0) + ofs \- idx * sizeof(QByteArrayData)) \)/********offsetof(qt_meta_stringdata_ParseQObject_t, stringdata0)  stringdata0 在 qt_meta_stringdata_ParseQObject_t中的偏移宏拆开后,对应一个QByteArrayData{ -1, len, //字符串长度0, 0, qptrdiff(offsetof(qt_meta_stringdata_ParseQObject_t, stringdata0) - idx * sizeof(QByteArrayData) + ofs ) //是对应stringdata0中此字段字符串中的首地址}//qt_meta_stringdata_ParseQObject_t, stringdata0) 字符串在结构体的偏移 256//qptrdiff(offsetof(qt_meta_stringdata_ParseQObject_t, stringdata0) - idx * sizeof(QByteArrayData) QByteArrayData data[16] ,数组元素[i]在结构体的偏移// 上式 + ofs(字符串的偏移) 即为求字符串的地址sizeof(QByteArrayData) = 16;假设stringdata0在qt_meta_stringdata_ParseQObject_t的偏移为19*16sig_2的索引为2则QBytearrayData data[2]= {-1,len,0,0,offset=19*16 - 2 * 16 + 18;为什么不是19*16 + 18呢?即为什么不是直接字符串首地址加偏移呢?答:因为QByteArrayData 求数据函数data定义为 void *data(){Q_ASSERT(size == 0|| offset < 0 || size_t(offset) >= sizeof(QArrayData));return reinterpret_cast<char *>(this) + offset; //此处的this 为data[2]的地址,data[2]的地址为 2 * sizeof(QByteArrayData),如果不减去data[2]的偏移,则相当于从data[2]开始+偏移+stringdata0的偏移,取到的是错误的地址//所以减去data[2]相对于qt_meta_stringdata_ParseQObject_t的偏移,将偏移定位到qt_meta_stringdata_ParseQObject_t的首地址0处}}data[0]的地址:  ParseQObject            = 19*16 - 0 * 16 + 0 data[1]的地址:  sig1                    = 19*16 - 1 * 16 + 13 sig2sigParam2intsig3sigParam3charsigParam3intslot1slot2slotParam2slot3slotParam3charslotPram3intInvokeFuncdata[15]的地址: InvokeFuncWithReturn     = 19*16 - 15* 16 + 137 ...data[18]的地址:prop1                    = 19*16 - 18 * 16 + 197
********/
*/
#define QT_MOC_LITERAL(idx, ofs, len) \Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \qptrdiff(offsetof(qt_meta_stringdata_ParseQObject_t, stringdata0) + ofs \- idx * sizeof(QByteArrayData)) \)
static const qt_meta_stringdata_ParseQObject_t qt_meta_stringdata_ParseQObject = {{//(0:索引, 0:对应字符串的偏移, 12:字符串的长度)  即"ParseQObject"
QT_MOC_LITERAL(0, 0, 12), // "ParseQObject"
QT_MOC_LITERAL(1, 13, 4), // "sig1"
QT_MOC_LITERAL(2, 18, 0), // ""                   //参数为空
QT_MOC_LITERAL(3, 19, 4), // "sig2"
QT_MOC_LITERAL(4, 24, 12), // "sigParam2int"  //参数名
QT_MOC_LITERAL(5, 37, 4), // "sig3"
QT_MOC_LITERAL(6, 42, 13), // "sigParam3char"
QT_MOC_LITERAL(7, 56, 12), // "sigParam3int"
QT_MOC_LITERAL(8, 69, 5), // "slot1"
QT_MOC_LITERAL(9, 75, 5), // "slot2"
QT_MOC_LITERAL(10, 81, 10), // "slotParam2"
QT_MOC_LITERAL(11, 92, 5), // "slot3"
QT_MOC_LITERAL(12, 98, 14), // "slotParam3char"
QT_MOC_LITERAL(13, 113, 12), // "slotPram3int"
QT_MOC_LITERAL(14, 126, 10), // "InvokeFunc"
QT_MOC_LITERAL(15, 137, 20), // "InvokeFuncWithReturn"
QT_MOC_LITERAL(16, 158, 17), // "constructIntParam"
QT_MOC_LITERAL(17, 176, 20), // "constructParentParam"
QT_MOC_LITERAL(18, 197, 5) // "prop1"},"ParseQObject\0sig1\0\0sig2\0sigParam2int\0""sig3\0sigParam3char\0sigParam3int\0slot1\0""slot2\0slotParam2\0slot3\0slotParam3char\0""slotPram3int\0InvokeFunc\0InvokeFuncWithReturn\0""constructIntParam\0constructParentParam\0""prop1"
};
#undef QT_MOC_LITERAL
/*/
struct QMetaObjectPrivate
{// revision 7 is Qt 5.0 everything lower is not supported// revision 8 is Qt 5.12: It adds the enum name to QMetaEnumenum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbusint revision;int className;int classInfoCount, classInfoData;int methodCount, methodData;int propertyCount, propertyData;int enumeratorCount, enumeratorData;int constructorCount, constructorData;int flags;int signalCount;
};
/*/
static const uint qt_meta_data_ParseQObject[] = {// content:8,       // revision0,       // classname  对应QByteArrayData data[19]中的索引0,    0, // classinfo8,   14, // methods       8:信号槽与Q_INVOKABLE函数总数, 14:对应当前数组中的索引1,   82, // properties0,    0, // enums/sets2,   85, // constructors0,       // flags3,       // signalCount    3:信号总数// signals: name, argc, parameters, tag, flags1,    0,       54,      2,  0x06 /* Public */,// name:1:对应QByteArrayData data[16]中的索引,// argc:0:参数数量,// parameters:49:参数对应当前数组中的索引,// tag:2// flags:0x06:方法类型 0x02 | 0x04/*enum MethodFlags  {AccessPrivate = 0x00,AccessProtected = 0x01,AccessPublic = 0x02,AccessMask = 0x03, //maskMethodMethod = 0x00,MethodSignal = 0x04,MethodSlot = 0x08,MethodConstructor = 0x0c,MethodTypeMask = 0x0c,MethodCompatibility = 0x10,MethodCloned = 0x20,MethodScriptable = 0x40,MethodRevisioned = 0x80};*/3,    1,   55,    2, 0x06 /* Public */,5,    2,   58,    2, 0x06 /* Public */,// slots: name, argc, parameters, tag, flags8,    0,   63,    2, 0x0a /* Public */,9,    1,   64,    2, 0x0a /* Public */,11,    2,   67,    2, 0x0a /* Public */,// methods: name, argc, parameters, tag, flags14,    0,   72,    2, 0x02 /* Public */,15,    0,   73,    2, 0x02 /* Public */,// signals: parametersQMetaType::Void,QMetaType::Void, QMetaType::Int,    4,QMetaType::Void, QMetaType::Char, QMetaType::Int,    6,    7,// slots: parameters/*qt_meta_data_ParseQObject[54]*/QMetaType::Void,QMetaType::Void, QMetaType::Int,   10,QMetaType::Void,    QMetaType::Char, QMetaType::Int, 12,                13,//返回值类型(Void),    参数类型(Char),      参数类型(Int),     12:data[19]索引, 13:data[19]索引// methods: parametersQMetaType::Void,QMetaType::Int,// constructors: parameters//构造函数类型,因为有默认实参,所以生成使用默认实参,和不使用默认实参两种0x80000000 | 2, QMetaType::Int, QMetaType::QObjectStar,   16,   17,0x80000000 | 2, QMetaType::Int,   16,// properties: name, type, flags18,                     QMetaType::Int,         0x00095103,//18:data[19]索引,      QMetaType::Int 属性类型// constructors: name, argc, parameters, tag, flags0,    2,   74,    2, 0x0e /* Public */,0,    1,   79,    2, 0x2e /* Public | MethodCloned */,0        // eod
};
/*//调用方式enum QMetaObject::Call {InvokeMetaMethod,ReadProperty,WriteProperty,ResetProperty,QueryPropertyDesignable,QueryPropertyScriptable,QueryPropertyStored,QueryPropertyEditable,QueryPropertyUser,CreateInstance,IndexOfMethod,RegisterPropertyMetaType,RegisterMethodArgumentMetaType};
*/
void ParseQObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{if (_c == QMetaObject::CreateInstance) {//创建对象switch (_id) {//id为相对索引case 0: { ParseQObject *_r = new ParseQObject((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< QObject*(*)>(_a[2])));if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;case 1: { ParseQObject *_r = new ParseQObject((*reinterpret_cast< int(*)>(_a[1])));if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;default: break;}} else if (_c == QMetaObject::InvokeMetaMethod) {auto *_t = static_cast<ParseQObject *>(_o);Q_UNUSED(_t)switch (_id) {//id为相对索引case 0: _t->sig1(); break;case 1: _t->sig2((*reinterpret_cast< int(*)>(_a[1]))); break;case 2: _t->sig3((*reinterpret_cast< char(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;case 3: _t->slot1(); break;case 4: _t->slot2((*reinterpret_cast< int(*)>(_a[1]))); break;case 5: _t->slot3((*reinterpret_cast< char(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2]))); break;case 6: _t->InvokeFunc(); break;case 7: { int _r = _t->InvokeFuncWithReturn();if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); }  break;default: ;}} else if (_c == QMetaObject::IndexOfMethod) {int *result = reinterpret_cast<int *>(_a[0]);{using _t = void (ParseQObject::*)();if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ParseQObject::sig1)) {*result = 0;return;}}{using _t = void (ParseQObject::*)(int );if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ParseQObject::sig2)) {*result = 1;return;}}{using _t = void (ParseQObject::*)(char , int );if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ParseQObject::sig3)) {*result = 2;return;}}}
#ifndef QT_NO_PROPERTIESelse if (_c == QMetaObject::ReadProperty) {//读取属性值auto *_t = static_cast<ParseQObject *>(_o);Q_UNUSED(_t)void *_v = _a[0];switch (_id) {case 0: *reinterpret_cast< int*>(_v) = _t->prop1(); break;default: break;}} else if (_c == QMetaObject::WriteProperty) {//修改属性值auto *_t = static_cast<ParseQObject *>(_o);Q_UNUSED(_t)void *_v = _a[0];switch (_id) {case 0: _t->setProp1(*reinterpret_cast< int*>(_v)); break;default: break;}} else if (_c == QMetaObject::ResetProperty) {}
#endif // QT_NO_PROPERTIES
}
/*
//QMetaObject定义
struct Q_CORE_EXPORT QMetaObject
{struct { // private dataconst QMetaObject *superdata;const QByteArrayData *stringdata;const uint *data;typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);StaticMetacallFunction static_metacall;const QMetaObject * const *relatedMetaObjects;void *extradata; //reserved for future use} d;
}
*/
QT_INIT_METAOBJECT const QMetaObject ParseQObject::staticMetaObject = { {&QObject::staticMetaObject,               //const QMetaObject *superdata;qt_meta_stringdata_ParseQObject.data,    //const QByteArrayData *stringdata;qt_meta_data_ParseQObject,               //typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);//StaticMetacallFunction static_metacall;qt_static_metacall,nullptr,nullptr
} };const QMetaObject *ParseQObject::metaObject() const
{return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}void *ParseQObject::qt_metacast(const char *_clname)
{if (!_clname) return nullptr;if (!strcmp(_clname, qt_meta_stringdata_ParseQObject.stringdata0))return static_cast<void*>(this);return QObject::qt_metacast(_clname);
}int ParseQObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{_id = QObject::qt_metacall(_c, _id, _a);if (_id < 0)return _id;if (_c == QMetaObject::InvokeMetaMethod) {if (_id < 8)qt_static_metacall(this, _c, _id, _a);_id -= 8;} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {if (_id < 8)*reinterpret_cast<int*>(_a[0]) = -1;_id -= 8;}
#ifndef QT_NO_PROPERTIESelse if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty|| _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {qt_static_metacall(this, _c, _id, _a);_id -= 1;} else if (_c == QMetaObject::QueryPropertyDesignable) {_id -= 1;} else if (_c == QMetaObject::QueryPropertyScriptable) {_id -= 1;} else if (_c == QMetaObject::QueryPropertyStored) {_id -= 1;} else if (_c == QMetaObject::QueryPropertyEditable) {_id -= 1;} else if (_c == QMetaObject::QueryPropertyUser) {_id -= 1;}
#endif // QT_NO_PROPERTIESreturn _id;
}// SIGNAL 0
void ParseQObject::sig1()
{QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}// SIGNAL 1
void ParseQObject::sig2(int _t1)
{//生成信号调用void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };QMetaObject::activate(this, &staticMetaObject, 1, _a);
}// SIGNAL 2
void ParseQObject::sig3(char _t1, int _t2)
{void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };QMetaObject::activate(this, &staticMetaObject, 2, _a);
}
QT_WARNING_POP
QT_END_MOC_NAMESPACE

Qt Moc 文件解析相关推荐

  1. QT pro文件解析

    在QT中使用qmake自动生成pro文件,如果要自己定制工程选项,则需要自行修改pro文件. pro文件有以下关键字:TEMPLATE.TARGET.DESTDIR.DEPENDPATH.INCLUD ...

  2. vs生成qt moc文件

    1. 右键需要生成moc文件的头文件 2. 将生产的moc加入工程中

  3. Qt / Moc 和信号 - 槽解析

    目录 一. MOC 二. moc_test.cpp 分析 三. connect 四. activate 五. 总结 版本 Qt5.12.3 moc_test.cpp 位于可执行文件目录下,其余源代码都 ...

  4. Qt工作笔记-undefined reference to `vtable for MyObject'及对moc文件的进一步理解

    源码如下: main.cpp #include <QApplication> #include <QObject> #include <QTextCodec>cla ...

  5. 解决VS+QT无法生成moc文件的问题

    解决VS+QT无法生成moc文件的问题 参考文章: (1)解决VS+QT无法生成moc文件的问题 (2)https://www.cnblogs.com/pupilLZT/p/10760399.html ...

  6. Qt中Q_OBJECT与生成的moc文件的作用

    一.先来了解Q_OBJECT 只有继承了QObject类的类,才具有信号槽的能力.所以,为了使用信号槽,必须继承QObject.凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写 ...

  7. VS2015——Qt工程不能生成moc文件的解决办法

    问题:在VS2015开发Qt应用程序时发现,编译器提示无法关联信号槽,无法经过moc工具生成相关函数. 解决办法: 1.找到无法生成转换的槽函数头文件,右键头文件(xxx.h)-->找到属性选项 ...

  8. VS2017 下QT工程不能生成moc文件的解决方法

    1.选择要moc的类的头文件,鼠标右键属性,配置属性->常规,在项类型中将C/C++ 标头,改为自定义生成工具 2.左侧点击自定义生成工具,下方的常规,配置如下 命令行:"$(QTDI ...

  9. Qt pro 文件详解

     Qt pro 文件详解 1. TEMPLATE  变量TEMPLATE描述了为建立目标文件而采用何种模板,即生成何种形式的Makefile文件.Qmake  工具定义了5种模板:   a. 应用 ...

  10. qmake language qt 工程文件 配置文件 .pro .prl .prf .pri 词法 语法 for循环 判断语句 函数定义

    目录 词法 string 1.数据类型 2.特殊处理的内置变量 3.转义字符 关键字:包括语法关键字.特殊变量 语法 变量 变量.属性.环境变量 变量使用 全局变量作用域 函数定义和使用 判断语句和循 ...

最新文章

  1. Go 分布式学习利器(8)-- Go的函数
  2. centos 系统使用verdaccio搭建npm私库
  3. .NET中属性和特性
  4. 加上2T硬盘再装系统遇到问题
  5. Extjs 动态生成表格
  6. linux解决windows应用程序,关于Linux下使用Windows应用程序的尝试总结
  7. python规则框架_Pytest框架【2】:用例规则
  8. 【ArcGIS遇上Python】Python批量将多个文件夹下的多个影像数据镶嵌至新栅格
  9. (转) Dockerfile 中的 COPY 与 ADD 命令 1
  10. 第1章 游戏之乐——光影切割问题
  11. Windows:定时/进程结束执行命令
  12. NGINX 自动列目录
  13. 决策树算法 (CART分类树)
  14. linux版本qq,QQLinux版下载-QQ for Linux下载v2.0.0 最新版-西西软件下载
  15. 一点笔记,好记性不如烂笔头
  16. Mac系统中 alt+insert怎么操作?
  17. 计算机桌面英文翻译,电脑显示器英语怎么说
  18. java中定义变量名时大写_,【Java】变量命名规范
  19. 学校计算机培训计划怎么写,学校计算机培训计划_共3篇.doc
  20. 浏览器必备插件|2022版

热门文章

  1. 有一种加班,叫别人还没走!
  2. 山东省软件设计大赛参赛经验
  3. kernelbase故障模块_错误模块名称: KERNELBASE.dll
  4. 利用DataEase的关联数据集制作宽表
  5. 《蜗居》触动人心灵的100个瞬间
  6. dubbo学习之本地存根实践
  7. php有个schost.exe_svchost.exe是什么
  8. jquery gotop插件
  9. cetnos下gotop安装和使用
  10. 未来三年的移动互联网创业----创新工场创始合伙人汪华 在移动开发者大会上的演讲