Determine signals connected to a given slot in Qt
Asked Answered
D

3

35

I've injected myself into a Qt application, and I'm attempting to figure out what signals a given slot is connected to, but can't find any information on doing this. Is there a mechanism for doing this out of the box? If so, is this exposed to QtScript? (If not, I can wrap it easily enough.)

If there is no such mechanism, what would be the best way to add it? I cannot manipulate the existing application outside of simple hooking, but I could hook QObject::connect and store the connections myself, just not sure if that's the best way to go about it.

Disapprobation answered 3/5, 2010 at 1:10 Comment(0)
D
5

After digging around in the Qt code base and documentation (I got lots of helpful tips from here and elsewhere), I ended up settling on hooking QObject::connect (the static overload). Why? Well, the other solutions require you to know what objects are providing the signals, dig into private fields, or have to have a debug build of Qt. In the end, hooking QObject::connect gives you everything connected in the application, and you can trivially map back to the slots.

Disapprobation answered 3/5, 2010 at 8:40 Comment(0)
J
37

I think Qt stores the slots a given signal is connected to, so that when you emit it all receivers are called, therefore you can access the list of receivers:

For debugging purposes, you have:

void QObject::dumpObjectInfo ()

Dumps information about signal connections, etc. for this object to the debug output.

This function is useful for debugging, but does nothing if the library has been compiled in release mode (i.e. without debugging information).

And the list of slots a signal is connected:

int QObject::receivers ( const char * signal ) const [protected]

Returns the number of receivers connected to the signal.

The metaObject() gives you the QMetaMethod for the slot, but it has no information about its connections.

However, if you know the objects, you can go over all the the signals (using the meta object, testing the method type for signal) and build a reverse index with the slots receivers() gives you.

Justiciable answered 3/5, 2010 at 1:45 Comment(1)
Thanks for the info. Is there any facility to do this without knowing the objects? That's really the issue I'm running into at the moment.Disapprobation
Y
11

There is no way to safely iterate the list of signal-slot connections without holding Qt's internal mutexes/semaphores. The signals and slots can come and go at any time, so at best you'd get a list that is not guaranteed to be correct - and thus useless.

Whatever hooking you do in QObject::connect is by itself insufficient. The data you get from such hooks will suffer the following:

  1. You may have pointers to objects that are already deleted by the time you try to access them. You can mitigate this by using QPointer, but this only works for objects that live in the thread where you run your code. You'd need to inject your object into other threads to collect object lists there.

  2. You may have connections that don't exist anymore. Even hooking QObject::disconnect would be insufficient, since connections are deleted when objects cease to exist.

The problem you're facing is quite complex, and any robust solution would not be merely limited to "hooking" QObject::connect.

Alas, you haven't said why you need the list of signals that attach to a slot. What is the purpose of it?

Yahwistic answered 6/1, 2014 at 21:47 Comment(0)
D
5

After digging around in the Qt code base and documentation (I got lots of helpful tips from here and elsewhere), I ended up settling on hooking QObject::connect (the static overload). Why? Well, the other solutions require you to know what objects are providing the signals, dig into private fields, or have to have a debug build of Qt. In the end, hooking QObject::connect gives you everything connected in the application, and you can trivially map back to the slots.

Disapprobation answered 3/5, 2010 at 8:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.