Senior --Qt Qt Meta-Object System source code parsing

A, Qt Meta-Object System Introduction

1, Introduction to Meta-Object System

Qt signal slots and for introspection attributes based on the capability of the system at run-time, so-called introspection refers to the ability of an object-oriented language query object information during operation, such as if the language capabilities other type having the inspection object during operation, introspection is then typed (type intropection), the typed introspection be used to implement polymorphism.
C ++ relatively limited introspection, supports only typed introspection, the typed C ++ is achieved by introspection type identification (RTTI) (Run-Time Type Information) in the keyword typeid and dynamic_cast runtime.
Qt expand the introspection of C ++, but does not use the C ++ RTTI, but provides a more powerful meta-object (meta object) mechanism to achieve introspection. Based introspection, methods and properties can be listed in the list of objects, and can acquire all the information about the object, such as parameter types. Without introspection, QtScript and QML is difficult to achieve.
Qt element object in the system stands for Meta Object System, an extension is based on standard C ++, provide signals and slots mechanism Qt, type information in real time, dynamic system properties. QObject element object class based system, the Q_OBJECT macro moc MOC implemented.
A, QObject class
as the base class of each element need to use a target system.
B, Q_OBJECT macro
defined in the private data section of each class, to enable function element object, such as dynamic properties, signals and slots.
In a QObject class or a derived class, if not declared Q_OBJECT macro, then metaobject object class will not be generated, the class instance calls metaObject () returns the object is metaobject its parent, the consequences resulting from an instance of the class in fact, metadata is data obtained by the parent class. Therefore, the class definitions and declarations of signals and slots can not be used, therefore, inherited from QObject out of any class, regardless of whether the signal defining declaration, slots and properties, should be declared Q_OBJECT macros.
C, moc MOC (Meta - Object Complier in),
MOC Analysis C ++ source file, if found to contain Q_OBJECT macro definitions in a header (header file), the dynamic generation will be a moc_xxxx named C ++ source file, the source file contains Q_OBJECT implementation code will be compiled, linked to a class of binary code, as an integral part of the class.

Function 2, the meta-object system

In addition the system provides a signal element object function communication slots mechanism between objects, provides the following functions:
QObject :: as Metaobject () method of
obtaining a meta-object associated class
:: className () method QMetaObject
returns during operation the class name of an object, do not require local RTTI C ++ compiler (run-time type information) support
QObject :: inherits () method
is used to generate a determination is not the object class inherits from a particular class, it is to be QObject class among the classes derived directly or indirectly.
QObject :: tr () and QObject :: trUtf8 ()
is an international software translation string
:: setProperty () and QObject :: property () QObject
based on the attribute name dynamically set and get property values
  in use qobject_cast () method QObject provides dynamic switching between classes, the function qobject_cast () method is similar to the standard C ++ of dynamic_cast (), but qobject_cast () does not require RTTI support.

3, Q_PROPERTY () using

#define Q_PROPERTY(text)

Q_PROPERTY defined in /src/corelib/kernel/Qobjectdefs.h file, for being processed MOC.

Q_PROPERTY(type name
            READ getFunction
            [WRITE setFunction]
            [RESET resetFunction]
            [NOTIFY notifySignal]
            [REVISION int]
            [DESIGNABLE bool]
            [SCRIPTABLE bool]
            [STORED bool]
            [USER bool]
            [CONSTANT]
            [FINAL])

Type: type attribute
Name: the name attribute
READ getFunction: attribute access functions
WRITE setFunction: property setting function
RESET resetFunction: attribute reset function
notifySignal signal where the attribute changes emitted: the NOTIFY notifySignal
int the REVISION: version attribute, property exposed to QML in
DESIGNABLE bool: properties GUI designer is visible, defaults to true
SCRIPTABLE BOOL: whether the property can be scripting engine access, the default is to true
STORED BOOL:
the USER BOOL:
cONSTANT: the value of the identifier property is a constant, the value of not to attribute constant WRITE, NOTIFY
FINAL: identifying attributes derived class will not be overwritten
Note: NOTIFY notifySignal declared emission notifySignal signal when property changes, but did not realize, so programmers need to launch notifySignal where property changes signal.
Object.h:

#ifndef OBJECT_H
#define OBJECT_H

#include <QObject>
#include <QString>
#include <QDebug>

class Object : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int age READ age  WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(int score READ score  WRITE setScore NOTIFY scoreChanged)
    Q_CLASSINFO("Author", "Scorpio")
    Q_CLASSINFO("Version", "1.0")
    Q_ENUMS(Level)
protected:
    QString m_name;
    QString m_level;
    int m_age;
    int m_score;
public:
    enum Level
    {
        Basic,
        Middle,
        Advanced
    };
public:
    explicit Object(QString name, QObject *parent = 0):QObject(parent)
    {
        m_name = name;
        setObjectName(m_name);
        connect(this, SIGNAL(ageChanged(int)), this, SLOT(onAgeChanged(int)));
        connect(this, SIGNAL(scoreChanged(int)), this, SLOT(onScoreChanged(int)));
    }

    int age()const
    {
        return m_age;
    }

    void setAge(const int& age)
    {
        m_age = age;
        emit ageChanged(m_age);
    }

    int score()const
    {
        return m_score;
    }

    void setScore(const int& score)
    {
        m_score = score;
        emit scoreChanged(m_score);
    }
signals:
    void ageChanged(int age);
    void scoreChanged(int score);
public slots:

     void onAgeChanged(int age)
     {
         qDebug() << "age changed:" << age;
     }
     void onScoreChanged(int score)
     {
         qDebug() << "score changed:" << score;
     }
};

#endif // OBJECT_H

Main.cpp:

#include <QCoreApplication>
#include "Object.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Object ob("object");

    //设置属性age
    ob.setProperty("age", QVariant(30));
    qDebug() << "age: " << ob.age();
    qDebug() << "property age: " << ob.property("age").toInt();

    //设置属性score
    ob.setProperty("score", QVariant(90));
    qDebug() << "score: " << ob.score();
    qDebug() << "property score: " << ob.property("score").toInt();

    //内省intropection,运行时查询对象信息
    qDebug() << "object name: " << ob.objectName();
    qDebug() << "class name: " << ob.metaObject()->className();
    qDebug() << "isWidgetType: " << ob.isWidgetType();
    qDebug() << "inherit: " << ob.inherits("QObject");

    return a.exec();
}

4, Q_INVOKABLE use

#define Q_INVOKABLE

Q_INVOKABLE defined in /src/corelib/kernel/Qobjectdefs.h file for the identified MOC.
Q_INVOKABLE macro is used to define a member function can be meta-object system calls, Q_INVOKABLE macro must be written before the return type of the function. As follows:
Q_INVOKABLE void invokableMethod ();
invokableMethod () function uses Q_INVOKABLE macro statement, invokableMethod () function will be registered in the meta-object system, you can call using QMetaObject :: invokeMethod ().
Q_INVOKABLE and QMetaObject :: invokeMethod by the Meta-Object System evoke, in Qt C ++ / QML mixed programming, cross-thread programming, Qt Service Framework and Qt / HTML5 mixed programming and in widespread use.
A, used in the cross-thread programming
how to call QObject method to stop it in the other thread? Qt provides a very friendly and clean solution: post an event to the event queue, handle events will call the main method of interest (requires thread has a running event loop). The triggering mechanism is implemented by the introspective method MOC provided. Accordingly, only the signal, and a method Q_INVOKABLE slot is marked to be able to be triggered by other threads invoked. If you do not want to implement the method in the other thread QObject call to stop the signal, this method slots across threads. Another option is for declaring the methods Q_INVOKABLE, and invokeMethod evoke in another thread with.
B, Qt Service Framework
Qt Service Framework Qt Mobility 1.0.2 version is launched, a service (service) is a separate component to the client (client) defined operations. The client can check ××× through the interface name of the service, and the version number of objects and services. After finding the service, start the service and returns a frame pointer.
Service is implemented through plug-ins (plug-ins). To prevent clients rely on a specific library services must inherit from QObject, QMetaObject ensure the system can be used to provide dynamic discovery of services and the ability to wake up. For QmetaObject adequate mechanisms work, the service must meet all of its methods are implemented by signal, slot, property or invokable method and Q_INVOKEBLE.

QServiceManager manager;
QObject *storage ;  
storage = manager.loadInterface("com.nokia.qt.examples.FileStorage"); 
if(storage)     
    QMetaObject::invokeMethod(storage, "deleteFile", Q_ARG(QString, "/tmp/readme.txt")); 

InvokeMethod code provided by the above method service element object, call the object's file storage the deleteFile () method. The client does not need to know the type of object, so there is no link to a specific service libraries. In the course of the server deleteFile method, it must be marked as Q_INVOKEBLE, was recognized by the system element object.
A highlight Qt Service Framework is that it supports cross-process communication, service can accept remote process. After registering in the service manager, process through signal, slot, invokable method and property to communicate as if they were local objects. Service can be set to be shared between the client, or for a client. Prior to the introduction of Qt Service Framework, signals, slots and invokable method only supports cross-thread. The figure is the cross-process service / customer communications schematic section. invokable method and Q_INVOKEBLE stepped into the city is an important tool for communication between objects across threads.
Senior --Qt Qt Meta-Object System source code parsing

Two, Qt analytical element object system source code

1, Q_OBJECT macro definition

Any class derived from QObject contains its own metadata model, generally defined by the macro Q_OBJECT.
Q_OBJECT defined in /src/corelib/kernel/Qobjectdefs.h file.

#define Q_OBJECT \
public: \
    Q_OBJECT_CHECK \
    static const QMetaObject staticMetaObject; \
    Q_OBJECT_GETSTATICMETAOBJECT \
    virtual const QMetaObject *metaObject() const; \
    virtual void *qt_metacast(const char *); \
    QT_TR_FUNCTIONS \
    virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
    Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
    Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);

QMetaObject type of static member variables staticMetaObject is a data structure metadata. metaObject, qt_metacast, qt_metacall, qt_static_metacall four virtual function implemented by the MOC in the generated moc_xxx.cpp file. MetaObject effect is obtained metadata table pointer; qt_metacast effect is obtained pointer to signature structure according to the relevant return void * pointer; qt_metacall action look-up table is then calls the call related functions; qt_static_metacall effect element method is to call (signal and groove).
#define Q_DECL_HIDDEN __attribute__((visibility("hidden")))

2, QMetaObject type

QMetaObject in /src/corelib/kernel/Qobjectdefs.h class definition file.

struct Q_CORE_EXPORT QMetaObject
{
  ...
enum Call {
    InvokeMetaMethod,
    ReadProperty,
    WriteProperty,
    ResetProperty,
    QueryPropertyDesignable,
    QueryPropertyScriptable,
    QueryPropertyStored,
    QueryPropertyEditable,
    QueryPropertyUser,
    CreateInstance
};

   int static_metacall(Call, int, void **) const;
   static int metacall(QObject *, Call, int, void **);
  struct { // private data
    const QMetaObject *superdata;
    const char *stringdata;
    const uint *data;
    const void *extradata;
  } d;
};

QMetaObject has a nested structure encapsulates all data:
const QMetaObject  superdata; metadata base class class // metadata represented
const char 
StringData; // tag signature metadata
const uint * data; // Metadata array index pointer
const QMetaObject ** extradata; // pointer extended metadata table, point QMetaObjectExtraData data structure.

struct QMetaObjectExtraData
{
#ifdef Q_NO_DATA_RELOCATION
    const QMetaObjectAccessor *objects;
#else
    const QMetaObject **objects;
#endif

    typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); //from revision 6
    //typedef int (*StaticMetaCall)(QMetaObject::Call, int, void **); //used from revison 2 until revison 5
    StaticMetacallFunction static_metacall;
};

Object :: static_metacall is a pointer to a function pointer qt_static_metacall.

3, QT_TR_FUNCTIONS macro definition

Translation and macro QT_TR_FUNCTIONS is related.

#define QT_TR_FUNCTIONS \
  static inline QString tr(const char *s, const char *c = 0) \
  { return staticMetaObject.tr(s, c); } \
#endif

4, Qt other macro definitions

Qt defines a number of macros in /src/corelib/kernel/Qobjectdefs.h file.

#ifndef Q_MOC_RUN
# if defined(QT_NO_KEYWORDS)
#  define QT_NO_EMIT
# else
#   define slots
#   define signals protected
# endif
# define Q_SLOTS
# define Q_SIGNALS protected
# define Q_PRIVATE_SLOT(d, signature)
# define Q_EMIT
#ifndef QT_NO_EMIT
# define emit
#endif
#define Q_CLASSINFO(name, value)
#define Q_INTERFACES(x)
#define Q_PROPERTY(text)
#define Q_PRIVATE_PROPERTY(d, text)
#define Q_REVISION(v)
#define Q_OVERRIDE(text)
#define Q_ENUMS(x)
#define Q_FLAGS(x)
#define Q_SCRIPTABLE
#define Q_INVOKABLE
#define Q_SIGNAL
#define Q_SLOT

Most macros Qt no actual definition, are supplied to the recognition process MOC, MOC moc_xxx.cpp tool generates a class file analysis processing by the macro.
In Qt4 and earlier versions, signals are expanded into protected. Qt5 becomes public, to support the new syntax.

Third, moc MOC

1, MOC function

A, the processing Q_OBJECT macros and signals / slots keyword, generates the underlying code signal and grooves
B, processing Q_PROPERTY () and Q_ENUM () generating property system code
C, treated Q_FLAGS () and Q_CLASSINFO () generate additional class meta information
D, the process does not require MOC code may comprise a predefined macro up as follows:

#ifndef Q_MOC_RUN
…
#endif

2, MOC limit

A, a template class can not use the signal / slot mechanism
B, MOC is not a macro expansion, and the signal can not be defined using macro grooves, connect comprising time signals and do not use the macro name and a parameter channel
C, a plurality of classes derived from when, QObject derived classes must be placed first. When QObject (or subclass) one parent class as multiple inheritance, it is necessary to put it first. If multiple inheritance, MOC assumes that the process is a first class that inherits QObject subclass, first of all the need to ensure an inherited class or subclass is QObject.
D, can not function pointer as a parameter or a signal slot, is more complex because of its format, MOC can not handle. Typedef can define it as a simple form of reuse.
E, and the signal parameters do with the type of groove or typedef enum type must be fully qualified. The Chinese do not know how to translate the word is appropriate, simply means that, if the class is defined, the path must be the class or namespace paths together, to prevent confusion. Such as Qt :: Alignment and the like, in front of the Qt Alignment is the qualifier, it must be added, and there are a few levels plus a few levels.
F., And the slot can not return a reference signal type
G, signals, and slots can be placed region keywords and grooves defined signal, such as can not put the other, like the constructor defined variables, friend declaration signal can not be located or the groove area Statement .
H, and the signal can not contain nested class groove 
MOC unable to process signals and slots nested classes, errors example: 
class A: public QObject
{
the Q_OBJECT
public:
class B
{
public slots: // WRONG

};

};
The I, the signal can not have default parameters groove

3, custom types of registration

When transmitting a custom type of data between Qt threads, their type definition if to pass directly signal slots would arise following this error:
          QObject :: Connect: Can Not Queue arguments of type 'xxxxx' (the Make Sure 'xxxxx' IS registed . using qRegisterMetaType ())
         reason: when a signal is put in the queue (queued), the parameters (arguments) will be put together with the queue, parameters need to be copied before being sent to slot, stored in the queue ; in order to be able to store parameters (argument), Qt need to construct in the queue, destruct, copy parameter object, and in order to make Qt know how to do these things, the type of parameters that need to use qRegisterMetaType to register.
XXXXX step to customize the type :( Example)
A, the top of the custom class type comprising: #include <QMetaType>
B, after the type defined, the statement added: Q_DECLARE_METATYPE (XXXXX);
C, the main () function register custom class types: qRegisterMetaType <xXXXX> ( "xXXXX ");
If you want to use a reference type, the same to be registered: qRegisterMetaType <xXXXX> ( "xXXXX &");

4, MOC use

Check the Makefile project can be found to command MOC generate moc_xxx.cpp file:

moc_Object.cpp: ../moc/Object.h
    /usr/local/Trolltech/Qt-4.8.6/bin/moc $(DEFINES) $(INCPATH) ../moc/Object.h -o moc_Object.cpp
因此命令行可以简化为:
`moc Object.h -o moc_Object.cpp`

Guess you like

Origin blog.csdn.net/u014421422/article/details/90740981