Qt Moc文件详解
Moc文件内容
Moc 文件是Qt moc工具生成的实现文件,用于实现Qt的元对象系统
类原始代码
class ParseQObject : public QObject
{
Q_OBJECT
Q_PROPERTY(int prop1 READ prop1 WRITE setProp1)// 属性1
public:
explicit ParseQObject(QObject *parent = nullptr);
//can create instance constructor 1
Q_INVOKABLE ParseQObject(int constructIntParam, QObject *constructParentParam = nullptr);
signals:
void sig1();//信号1
void sig2(int sigParam2int);//信号2
void sig3(char sigParam3char, int sigParam3int);//信号3
public slots:
void slot1();//槽1
void slot2(int slotParam2);//槽2
void slot3(char slotParam3char, int slotPram3int);//槽3
public:
Q_INVOKABLE void InvokeFunc();//invoke function 1
Q_INVOKABLE int InvokeFuncWithReturn();//invoke func 2
int 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 header
void *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*16
sig_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
sig2
sigParam2int
sig3
sigParam3char
sigParam3int
slot1
slot2
slotParam2
slot3
slotParam3char
slotPram3int
InvokeFunc
data[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 QMetaEnum
enum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbus
int 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, // revision
0, // classname 对应QByteArrayData data[19]中的索引
0, 0, // classinfo
8, 14, // methods 8:信号槽与Q_INVOKABLE函数总数, 14:对应当前数组中的索引
1, 82, // properties
0, 0, // enums/sets
2, 85, // constructors
0, // flags
3, // signalCount 3:信号总数
// signals: name, argc, parameters, tag, flags
1, 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, //mask
MethodMethod = 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, flags
8, 0, 63, 2, 0x0a /* Public */,
9, 1, 64, 2, 0x0a /* Public */,
11, 2, 67, 2, 0x0a /* Public */,
// methods: name, argc, parameters, tag, flags
14, 0, 72, 2, 0x02 /* Public */,
15, 0, 73, 2, 0x02 /* Public */,
// signals: parameters
QMetaType::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: parameters
QMetaType::Void,
QMetaType::Int,
// constructors: parameters
//构造函数类型,因为有默认实参,所以生成使用默认实参,和不使用默认实参两种
0x80000000 | 2, QMetaType::Int, QMetaType::QObjectStar, 16, 17,
0x80000000 | 2, QMetaType::Int, 16,
// properties: name, type, flags
18, QMetaType::Int, 0x00095103,
//18:data[19]索引, QMetaType::Int 属性类型
// constructors: name, argc, parameters, tag, flags
0, 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_PROPERTIES
else 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 data
const 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_PROPERTIES
else 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_PROPERTIES
return _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