Document directory
- Qmetaobject: classname ()
- Qmetaobject: superclass ()
- Qmetaobject: classinfocount ()
- Qmetaobject: classinfooffset ()
- Qmetaobject: classinfo (INT index)
- Qmetaobject: indexofclassinfo ()
- Int constructorcount () const
- Qmetamethod Constructor (INT index) const
- Int indexofconstructor (const char * constructor) const
- Intindexofsignal (const char * signal) const
- Qmetapropertyproperty (INT index) const
- Qmetapropertyuserproperty () const
This article explains the implementation of related interfaces from the source code of QT metaobject. These interfaces are defined in qmetaobject. cpp.
Qmetaobject: classname ()
Inline const char * qmetaobject: classname () const
{Return D. stringdata ;}
From the previous article, we can see that D. stringdata is the string data that contains several C strings ending with '/0. If D. stringdata is treated as a C string pointer, it is the first string of the string sequence, and it is the class name.
Qmetaobject: superclass ()
Inline const qmetaobject * qmetaobject: superclass () const
{Return D. superdata ;}
Qmetaobject: classinfocount ()
Int qmetaobject: classinfocount () const
{
Int n = priv (D. Data)-> classinfocount;
Const qmetaobject * m = D. superdata;
While (m ){
N + = priv (m-> D. Data)-> classinfocount;
M = m-> D. superdata;
}
Return N;
}
From the code, we can see that the number of all classinfo returned for this class includes the number of all base classes.
The priv function is a simple inline function:
Static inline const qmetaobjectprivate * priv (const uint * Data)
{Return reinterpret_cast <const qmetaobjectprivate *> (data );}
According to the previous article, D. data points to the binary information. priv interprets D. Data as qmetaobjectprivate.
Qmetaobjectprivate is the private implementation class of qmetaobject. Its data definition is as follows (see the header file qmetaobject_p.h ). It corresponds to the content of the previous example MOC file, and its meaning is clear at a glance.
Struct qmetaobjectprivate
{
Int revision;
Int classname;
Int classinfocount, classinfodata;
Int methodcount, methoddata;
Int propertycount, propertydata;
Int enumeratorcount, enumeratordata;
Int constructorcount, constructordata; // Since Revision 2
Int flags; // Since Revision 3
Int signalcount; // Since Revision
}
Qmetaobject: classinfooffset ()
Int classinfooffset () const
{
Int offset = 0;
Const qmetaobject * m = D. superdata;
While (m ){
Offset + = priv (m-> D. Data)-> classinfocount;
M = m-> D. superdata;
}
Return offset;
}
The meaning of this class is to return the starting index value of the classinfo defined by this class, which is equivalent to the number of classinfo defined by its ancestor class.
Qmetaobject: classinfo (INT index)
Qmetaclassinfo classinfo (INT index) const
{
Int I = index;
I-= classinfooffset ();
If (I <0 & D. superdata)
Return D. superdata-> classinfo (INDEX );
Qmetaclassinfo result;
If (I> = 0 & I <priv (D. Data)-> classinfocount ){
Result. mobj = this;
Result. Handle = priv (D. Data)-> classinfodata + 2 * I;
}
Return result;
}
The process of this Code is relatively simple. Priv (D. data)-> classinfodata is the information of classinfo in D. data offset; each classinfo information occupies the size of two uint, so "priv (D. data)-> classinfodata + 2 * I "the value of this expression is the information of the I classinfo in D. offset in data.
Qmetaobject: indexofclassinfo ()
Int indexofclassinfo (const char * Name) const
{
Int I =-1;
Const qmetaobject * m = this;
While (M & I <0 ){
For (I = priv (m-> D. Data)-> classInfoCount-1; I> = 0; -- I)
If (strcmp (name, M-> D. stringdata
+ M-> D. Data [priv (m-> D. Data)-> classinfodata + 2 * I]) = 0 ){
I + = m-> classinfooffset ();
Break;
}
M = m-> D. superdata;
}
Return I;
}
Find the classinfo with the name from the bottom up according to the inheritance level.
Refer to the interpretation of the previous function. The expression m-> D. data [priv (m-> D. data)-> classinfodata + 2 * I] is the first 32-bit value of the I-th classinfo information. This value is the index value in character information block D. stringdata. Therefore, M-> D. stringdata +
M-> D. Data [priv (m-> D. Data)-> classinfodata + 2 * I] is the string of the classinfo name.
Int constructorcount () const
Int qmetaobject: constructorcount () const
{
If (priv (D. Data)-> revision <2)
Return 0;
Return priv (D. Data)-> constructorcount;
}
Qmetamethod Constructor (INT index) const
Qmetamethod qmetaobject: Constructor (INT index) const
{
Int I = index;
Qmetamethod result;
If (priv (D. Data)-> revision> = 2 & I> = 0 & I <priv (D. Data)-> constructorcount ){
Result. mobj = this;
Result. Handle = priv (D. Data)-> constructordata + 5 * I;
}
Return result;
}
Int indexofconstructor (const char * constructor) const
Int qmetaobject: indexofconstructor (const char * constructor) const
{
If (priv (D. Data)-> revision <2)
Return-1;
For (INT I = priv (D. Data)-> constructorCount-1; I> = 0; -- I ){
If (strcmp (constructor, D. stringdata
+ D. Data [priv (D. Data)-> constructordata + 5 * I]) = 0 ){
Return I;
}
}
Return-1;
}
Int enumeratorcount () const
Int enumeratoroffset () const
Qmetaenum enumerator (INT index) const
Int indexofenumerator (const char * Name) const
The implementation of this group of functions is similar to that of classinfo.
Intmethodcount () const;
Intmethodoffset () const;
Qmetamethodmethod (INT index) const
{
Int I = index;
I-= methodoffset ();
If (I <0 & D. superdata)
Return D. superdata-> method (INDEX );
Qmetamethod result;
If (I> = 0 & I <priv (D. Data)-> methodcount ){
Result. mobj = this;
Result. Handle = priv (D. Data)-> methoddata + 5 * I;
}
Return result;
}
The implementation method of this function is also clear at a glance.
Intindexofmethod (const char * method) const omitted;
Intindexofsignal (const char * signal) const
{
Const qmetaobject * m = this;
Int I = qmetaobjectprivate: indexofsignalrelative (& M, signal );
If (I> = 0)
I + = m-> methodoffset ();
Return I;
}
Int qmetaobjectprivate: indexofsignalrelative (const qmetaobject ** baseobject, const char * signal)
{
Int I =-1;
While (* baseobject ){
Const qmetaobject * const M = * baseobject;
For (I = priv (m-> D. Data)-> methodCount-1; I> = 0; -- I)
If (m-> D. Data [priv (m-> D. Data)-> methoddata + 5 * I + 4] & methodtypemask) = methodsignal
& Strcmp (signal, M-> D. stringdata
+ M-> D. Data [priv (m-> D. Data)-> methoddata + 5 * I]) = 0 ){
Break;
}
If (I> = 0)
Break;
* Baseobject = m-> D. superdata;
}
}
It can be seen that the special feature of searching for signal is that the fifth item of method metadata is used to determine whether this is a signal.
Intindexofslot (const char * slot) const omitted;
Intpropertycount () const;
Intpropertyoffset () const;
Intindexofproperty (const char * Name) const omitted;
Qmetapropertyproperty (INT index) const
{
Int I = index;
I-= propertyoffset ();
If (I <0 & D. superdata)
Return D. superdata-> property (INDEX );
Qmetaproperty result;
If (I> = 0 & I <priv (D. Data)-> propertycount ){
Int handle = priv (D. Data)-> propertydata + 3 * I;
Int flags = D. Data [Handle + 2];
Const char * type = D. stringdata + D. Data [Handle + 1];
Result. mobj = this;
Result. Handle = handle;
Result. idx = I;
If (flags & enumorflag ){
Result. menum = enumerator (indexofenumerator (type ));
If (! Result. menum. isvalid ()){
Qbytearray enum_name = type;
Qbytearray scope_name = D. stringdata;
Int S = enum_name.lastindexof ("::");
If (S> 0 ){
Scope_name = enum_name.left (s );
Enum_name = enum_name.mid (S + 2 );
}
Const qmetaobject * scope = 0;
If (scope_name = "QT ")
Scope = & qobject: staticqtmetaobject;
Else
Scope = qmetaobject_findmetaobject (this, scope_name );
If (Scope)
Result. menum = scope-> enumerator (scope-> indexofenumerator (enum_name ));
}
}
}
Return result;
}
The special feature of this function is that if this propery is an enumeration type, the correct qmetaenum attribute value is assigned to the returned value qmetapropery.
Qmetapropertyuserproperty () const
{
Const int propcount = propertycount ();
For (INT I = propcount-1; I> = 0; -- I ){
Const qmetaproperty prop = property (I );
If (prop. isuser ())
Return prop;
}
Return qmetaproperty ();
}
From the implementation of this function, a qobject should have only one property that opens the user flag.