Frage

Diese Frage bereits in diesem Forum gefragt, aber ich verstehe nicht, das Konzept.

Ich las sich um und es scheint, dass Signal und Schlitze werden mit Funktionszeigern implementiert das heißt, das Signal ist eine große Funktion, die im Inneren alle angeschlossenen Schlitze (Funktionszeiger) aufruft. Ist das richtig? Und was ist die Rolle der erzeugten moc-Dateien in der ganzen Geschichte? Ich verstehe nicht, wie die Signalfunktion weiß, welche Schlitze nennen heißt, die Schlitze auf dieses Signal verbunden ist.

Vielen Dank für Ihre Zeit

War es hilfreich?

Lösung

Qt implementiert diese Dinge in einer Weise, die interpretierten Sprachen ähnelt. D. h es baut Symboltabellen, die Signalnamen auf Funktionszeiger Karte, hält sie und die Funktionszeiger von Funktionsnamen sucht, wo nötig.

Jedes Mal, wenn Sie ein Signal aussenden, das heißt write

emit something();

Sie die something() Funktion tatsächlich aufrufen, die sie automatisch vom Metaobjekt-Compiler erzeugt und in eine *.moc-Datei abgelegt. Innerhalb dieser Funktion wird es überprüft, welche Slots dieses Signal zur Zeit verbunden ist, und entsprechenden Steckplatz Funktionen (die Sie in Ihren eigenen Quellen implementiert) nacheinander über die Symboltabellen genannt (in der oben beschriebenen Weise). Und emit, wie andere Qt-spezifische Keywords, werden nur von C ++ Präprozessor verworfen, nachdem *.moc generiert wurden. Tatsächlich in einer der Qt-Header ( qobjectdefs.h ), gibt es solche Zeilen:

#define slots 
#define signals protected
#define emit

Verbindungsfunktion (connect) ändert nur die Symboltabellen innerhalb *.moc Dateien beibehalten, und die ihm übergebenen Argumente (mit SIGNAL() und `SCHLITZ-Makros) vorverarbeitet, um auch die Tabellen zu entsprechen.

Das ist die allgemeine Idee. In seiner weiteren Antwort, ジ ョ ー ジ liefert uns Links Mailingliste und auf eine andere Frage SO zu diesem Thema.

Andere Tipps

Ich glaube, ich sollte die folgende hinzuzufügen.

Es gibt anderen verbunden Frage - und es gibt < a href = "http://www.ntcore.com/files/qtrev.htm" rel = "nofollow noreferrer"> ein sehr guter Artikel dass als recht detailliert Expansion es ist answer ; hier ist dieser Artikel wieder , mit verbessertem (wenn auch noch nicht perfekt) Code Syntaxhervorhebung.

Hier ist meine kurze Nacherzählung davon, dass auf Fehler anfällig sein kann)

Im Grunde genommen, wenn wir die Q_OBJECT Makro in unserer Klassendefinition einfügen, der Präprozessor es zu einer statischen QMetaObject Instanz Erklärung erweitert, eine, die von allen Instanzen der gleichen Klasse geteilt werden würde:

class ClassName : public QObject // our class definition
{
    static const QMetaObject staticMetaObject; // <--= Q_OBJECT results to this

    // ... signal and slots definitions, other stuff ...

}

Dieses Beispiel wiederum wird bei der Initialisierung speichern Sie die Signaturen ("methodname(argtype1,argtype2)") der Signale und die Schlitze, welche den indexOfMethod() Anruf erlaubt zu implementieren, die durch sie, na ja, Methode des Index zurückgibt ist Unterschrift string:

struct Q_CORE_EXPORT QMetaObject
{    
    // ... skip ...
    int indexOfMethod(const char *method) const;
    // ... skip ...
    static void activate(QObject *sender, int signal_index, void **argv);
    // ... skip ...
    struct { // private data
        const QMetaObject *superdata; // links to the parent class, I guess
        const char *stringdata; // basically, "string1\0string2\0..." that contains signatures and other names 
        const uint *data; // the indices for the strings in stringdata and other stuff (e.g. flags)
        // skip
    } d;
};

Nun, wenn die moc die moc_headername.cpp Datei für die Klasse-Header headername.h Qt schafft, bringt es gibt die Signatur Strings und andere Daten, die für die korrekte Initialisierung der d Struktur erforderlich sind, und schreibt dann den Initialisierungscode für die staticMetaObject Singletons dies mit Daten.

Eine weitere wichtige Sache, die es tut, ist die Erzeugung des Code für die qt_metacall() Methode des Objekts, das die Methode eines Objektes ID und eine Reihe von Argumentzeiger und ruft die Methode über eine lange switch wie dies geschieht:

int ClassName::qt_metacall(..., int _id, void **_args)
{
    // ... skip ...
    switch (_id) {
        case 0: signalOrSlotMethod1(_args[1], _args[2]); break; // for a method with two args
        case 1: signalOrSlotMethod2(_args[1]); break; // for a method with a single argument
        // ... etc ...
    }
    // ... skip ...
}

Last, für jedes Signal moc erzeugt eine Implementierung, die einen QMetaObject::activate() Aufruf enthält:

void ClassName::signalName(argtype1 arg1, argtype2 arg2, /* ... */)
{
    void *_args[] = { 0, // this entry stands for the return value
                      &arg1, // actually, there's a (void*) type conversion
                      &arg2, // in the C++ style
                      // ...
                    };
    QMetaObject::activate( this, 
                           &staticMetaObject, 
                           0, /* this is the signal index in the qt_metacall() map, I suppose */ 
                           _args
                         );
}

Schließlich übersetzt der connect() Aufruf die Zeichenfolge Methodensignaturen, um ihre ganze Zahl IDs (die durch qt_metacall() verwendet sind) und führt eine Liste der Signal-zu-Slot-Verbindungen; wenn das Signal ausgesendet wird, geht der activate() Code durch diese Liste und ruft die entsprechende Objekt „Slots“ über ihre qt_metacall() Methode.

Um es zusammenzufassen, die statische QMetaObject Instanz speichert die „Meta-Informationen“ (Methodensignatur Strings usw.), eine erzeugte qt_metacall() Verfahren sieht „eine Methodentabelle“, die jedes Signal / Schlitz ermöglicht durch einen Index, Signal Implementierungen aufgerufen werden von moc erzeugt diese Indizes über activate() verwenden, und schließlich connect() macht den Job der Liste Signal-Slot-Index Karten beibehalten wird.

* Hinweis: Es gibt eine Komplikation dieser Regelung für den Fall verwendet werden, wenn wir Signale zwischen verschiedenen Threads liefern wollen (ich vermute, dass man an dem blocking_activate() Code aussehen muss), aber ich hoffe, dass die allgemeine Idee gleich bleibt)

Das ist mein sehr grobes Verständnis der verlinkten Artikel, die leicht falsch sein können, so dass ich nicht empfehle es direkt zu gehen und lesen)

PS. Als ich mein Verständnis von Qt Umsetzung verbessern möchten - lassen Sie es mich in meiner Nacherzählung von Widersprüchen kennen


Da meine anderen (früher) Antwort von einigen eifrigen Editor gelöscht wurde, werde ich den Text hier anhängen (Ich vermisse einige Details, die waren nicht integriert in Pavel Shved der Post, und ich bezweifle, die Person die gelöscht die Antwort gepflegt.)

@Pavel Shved:

  

Ich bin ziemlich sicher, dass irgendwo in Qt-Header eine Zeile vorhanden ist:

     

#define emit

Just zu bestätigen: fand es in alten Qt-Code von Google Code Search. Es ist sehr wahrscheinlich, dass es noch da ist); die gefundene location Weg war:

ftp://ftp.slackware-brasil.com.br > Slackware-7.1> contrib> kde-1.90> qt-2.1.1.tgz> usr> lib> qt-2.1.1> src> kernel> qobjectdefs.h


Ein weiterer complementory Link: http: //lists.trolltech .com / qt-interest / 2007-05 / thread00691-0.html - siehe die Antwort von Andreas Pakulat


Und hier ist ein weiteres Stück der Antwort: Qt Frage: Wie Signale und Slots arbeiten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top