osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Signals and Slots - Summerfield - what exactly is a signal?


On 08/05/2017 12:19 PM, Marko Rauhamaa wrote:
> I would express it as just saying that the Qt developers appropriated
> the word "signal" for what is simply a callback.

I'd say a slot is a callback.  A signal is the designation of something
that will trigger callbacks.

> Years back I took a brief loook at Qt. I had heard that one of their
> great selling points was that they did C++. At the time, C++ was my
> bread and butter, and I had been baffled at how bad C++ was at
> expressing such a basic thing as callbacks.
> 
> Turns out Qt didn't do callbacks using C++. Instead they specified a
> sort of macro language to express callbacks and offered what was known
> as a "metacompiler" that converted those macros into real C++.

Off-topic, but probably still worth talking about, since the OP does
appear interested in Qt internals and how they relate to Python.

As for Qt not being really C++, that's only partially true these days.
Qt code you write is actual C++, directly compile-able with any
standards-compliant C++ compiler. moc, the metacompiler you're referring
to, generates some helper code that is required to tie the Qt objects
together.  And you can argue this is only necessary because of
deficiencies in C++ (at least pre-STL days).  But this is no different
or burdensome than requiring a step to compile an XML ui file to code
like many/most UI toolkits do.

The biggest problem with moc in my mind is that it hides the fact that
signal emission is done by name in the Qt engine, using string lookups
and comparisons. In your code they look like actual identifiers but moc
generates string equivalents in the meta class code. This can lead to
really weird bugs.  It's been a long time since I ran into this problem
so I can't remember the specifics. I'm not sure if this problem would
manifest itself in Python code, but I suspect it might.

> It was a big disappointment both with respect to C++ and Qt.
> 
> Now, the Standard Template Library offered elaborate macros (aka functor
> templates) that allowed you to express callbacks with zero, one or two
> arguments (in a cumbersome way). Boost, a famous C++ class library,
> added functor support to three, four, five, six, seven, eight, nine,
> and--hear this!--TEN arguments.

Yeah Qt has never used templates because they didn't exist when Qt was
first started. Now I think you could use templates to do a lot of what
moc does, and indeed Gtkmm uses templates to make a very nice, very
native C++ binding for GTK+.  I have had to, on occasion, make my own
templates for gtkmm when the number of parameters I needed to bind was
different than the prefab templates provided.  Templates can be really
cumbersome.

One area that the template-based GTKmm really shone compared to Qt was
that, in C++ at least, signatures between the signal and slot were
checked at compile time, thanks to templates.  In Qt, they end up being
essentially bare function pointers (might get a runtime error? I can't
remember).

> All this nonsense because it hadn't occurred to Bjarne Stroustrup to
> define so-called method pointers in a sane manner. It was left to
> another Dane, Anders Hejlsberg, to demonstrate how they ought to have
> been defined, namely, as delegates (as in Delphi and C#). Unfortunately,
> it was too late for C++.
> 
> Now, I'm hearing C++ supports proper closures: <URL:
> http://en.cppreference.com/w/cpp/language/lambda>. I wonder if Qt would
> eventually migrate to them.
> 
> At any rate, Python never had to come up with such tricks for callbacks.
> Python's closure syntax is maybe the most natural there is. Too bad if
> PyQt confuses Python programmers with "signals" and "slots" when they
> are simply methods.

True enough. When you work with PyQt, unfortunately these C++ details do
leak through, which is the biggest weakness of PyQt (and also PySide).
So I guess that's reason enough to be familiar with the warts.

Despite the warts, PyQt is my go-to toolkit for doing the simple GUI
stuff I need, as it is easy to install and run on any platform and looks
great.  I wrote a simple compatibility shim to let me use both PySide
and PyQt4 with the same code.  That way if I need to release code in a
non-GPL way, I can just switch to PySide.

PySide had its own issues because of how the bindings are made. One of
them is that occasionally PySide drops a reference to a Qt C++ object,
which can lead to a segfault.

And I have no idea the state of PySide for Qt5.