Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Qt implement signals and slots?

Can someone explain to me the basic idea of Qt signals&slots mechanism IMPLEMENTATION? I want to know what all those Q_OBJECT macros do "in plain C++". This question is NOT about signals&slots usage.

added: I know that Qt uses moc compiler to transform Qt-C++ in plain C++. But what does moc do? I tried to read "moc_filename.cpp" files but I have no idea what can something like this mean

void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
    return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
like image 243
anton Avatar asked Jan 05 '10 17:01

anton


People also ask

How are signals and slots implemented in Qt?

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.

How do I add a signal to Qt?

To connect components to signals: Go to the Connections tab in the Connections view. Select the (Add) button to add a connection. Double-click the value in the Target column to add the component to connect to a signal.

Are Qt signals and slots thread safe?

It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.

What are Qt Public slots?

In C++, public means those members that are accessible from anywhere where the object is visible, private means that members are accessible only from within other members of the same class or from their friends. But in Qt, the difference in private slots and public slots seem not to exist.


2 Answers

Concerning the signals and slots, the Q_OBJECT macro adds a virtual function qt_metacall() declaration into the class’s declaration which is to be defined later by the the moc. (It also adds some declarations for conversion but that’s not too important here.)

The moc then reads the header file and when it sees the macro, it generates another .cpp file named moc_headerfilename.cpp with the definitions to the virtual functions and – you might have asked yourself why you can get away with mentioning the signals: in your header file without a proper definition – of the signals.

So, when a signal is called, the definition from the mocfile is executed and QMetaObject::activate() is called with the signal’s name and the signal’s arguments. The activate() function then figures out which connections have been established and fetches the names for the appropriate slots.

Then it calls qt_metacall with the slot names and the arguments given to the signal and the metacall function delegates this with the help of a large switchcase statement to the real slots.

As there is no real runtime information possible in C++ concerning the actual names for the signals and slots, as has already been noticed, these will be encoded by the SIGNAL and SLOT macros to simple const char*s (with either "1" or "2" added to the name to distinguish signals from slots).

As is defined in qobjectdefs.h:

#define SLOT(a)     "1"#a
#define SIGNAL(a)   "2"#a

The other thing the Q_OBJECT macro does is defining the tr() functions inside your object which can be used to translate your application.

Edit As you asked what the qt_metacast is doing. It checks whether an object belongs to certain class and if it does returns the pointer to it. If it doesn’t, it returns 0.

Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);

This is needed to provide some runtime reflection which is not possible otherwise. The function is called in QObject::inherits(const char *) for example and simply checks for inheritance.

like image 145
Debilski Avatar answered Oct 10 '22 21:10

Debilski


Those macros do absolutely nothing "in plain C++", - they expand to empty strings (I think).

QT uses a meta-object compiler, that generates C++ code for Q_OBJECT-enabled classes (implementing the signals/slots you define, among other things).

You can read more about it in the official documentation.

like image 23
shylent Avatar answered Oct 10 '22 21:10

shylent