Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I think I should add the following.</p> <p>There is <a href="https://stackoverflow.com/questions/2008033/how-does-qt-implement-signals-and-slots">another linked question</a> -- and there is <a href="http://www.ntcore.com/files/qtrev.htm" rel="nofollow noreferrer">a very good article</a> that can be considered as a quite detailed expansion to it's <a href="https://stackoverflow.com/questions/2008033/how-does-qt-implement-signals-and-slots/2008542#2008542">answer</a>; <a href="http://www.codeproject.com/Articles/31330/Qt-Internals-Reversing" rel="nofollow noreferrer">here is this article again</a>, with improved (though still not perfect) code syntax highlighting.</p> <p>Here's my short retelling of it, that may be prone to mistakes ) </p> <p>Basically when we insert the <code>Q_OBJECT</code> macro in our class definition, the preprocessor expands it to a static <code>QMetaObject</code> instance declaration, one that would be shared by all instances of the same class:</p> <pre><code>class ClassName : public QObject // our class definition { static const QMetaObject staticMetaObject; // &lt;--= Q_OBJECT results to this // ... signal and slots definitions, other stuff ... } </code></pre> <p>This instance, in turn, on initialization will store the <em>signatures</em> (<code>"methodname(argtype1,argtype2)"</code>) of the signals and the slots, what will allow to implement the <code>indexOfMethod()</code> call, which returns, well, method's index by it's signature string : </p> <pre><code>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; }; </code></pre> <p>Now when the <code>moc</code> creates the <code>moc_headername.cpp</code> file for the Qt class header <code>headername.h</code>, it puts there the signature strings and other data that are necessary for correct initialization of the <code>d</code> structure, and then writes the initialization code for the <code>staticMetaObject</code> singleton using this data. </p> <p>Another important thing it does is generation of the code for the object's <code>qt_metacall()</code> method, that takes an object's method id and an array of argument pointers and calls the method via a long <code>switch</code> like this: </p> <pre><code>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 ... } </code></pre> <p>Last, for every signal <code>moc</code> generates an implementation, which contains a <code>QMetaObject::activate()</code> call :</p> <pre><code>void ClassName::signalName(argtype1 arg1, argtype2 arg2, /* ... */) { void *_args[] = { 0, // this entry stands for the return value &amp;arg1, // actually, there's a (void*) type conversion &amp;arg2, // in the C++ style // ... }; QMetaObject::activate( this, &amp;staticMetaObject, 0, /* this is the signal index in the qt_metacall() map, I suppose */ _args ); } </code></pre> <p>Finally, the <code>connect()</code> call translates the string method signatures to their integer ids (the ones used by <code>qt_metacall()</code>) and maintains a list of signal-to-slot connections; when the signal is emitted, the <code>activate()</code> code goes through this list and calls the appropriate object "slots" via their <code>qt_metacall()</code> method. </p> <p>To sum up, the static <code>QMetaObject</code> instance stores the "meta-information" (method signature strings etc), a generated <code>qt_metacall()</code> method provides "a method table" that allows any signal/slot to be called by an index, signal implementations generated by <code>moc</code> use these indexes via <code>activate()</code>, and finally <code>connect()</code> does the job of maintaining a list of signal-to-slot index maps.</p> <p>*Note: there's a complication of this scheme used for the case when we want to deliver signals between different threads ( I suspect that one has to look at the <code>blocking_activate()</code> code ), but I hope the general idea remains the same )</p> <p>This is my very rough understanding of the linked article, which easily may be wrong, so I do recommend to go and read it directly )</p> <p>PS. As I'd like to improve my understanding of Qt implementation -- please let me know of any inconsistencies in my retelling !</p> <hr> <p>Since my other (earlier) answer was deleted by some zealous editor, I will append the text here ( I am missing few details that were <em>not</em> incorporated in Pavel Shved's post, and I doubt the person who deleted the answer cared. ) </p> <p>@Pavel Shved: </p> <blockquote> <p>I am pretty sure that somewhere in Qt headers there exists a line:</p> <p><code>#define emit</code></p> </blockquote> <p>Just to confirm: found it in old Qt code by Google Code Search. It is quite likely that it is still there ) ; the found location path was : </p> <p><a href="ftp://ftp.slackware-brasil.com.br" rel="nofollow noreferrer">ftp://ftp.slackware-brasil.com.br</a>› slackware-7.1› contrib› kde-1.90› qt-2.1.1.tgz› usr› lib› qt-2.1.1› src› kernel› <strong>qobjectdefs.h</strong></p> <hr> <p>Another complementory link: <a href="http://lists.trolltech.com/qt-interest/2007-05/thread00691-0.html" rel="nofollow noreferrer">http://lists.trolltech.com/qt-interest/2007-05/thread00691-0.html</a> -- see the answer by Andreas Pakulat </p> <hr> <p>And here is another piece of the answer : <a href="https://stackoverflow.com/questions/1368593/qt-question-how-do-signals-and-slots-work/1371958#1371958">Qt question: How do signals and slots work?</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload