Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. PySide6 D-Bus Signal Interface Not Emitting or Discoverable
Forum Updated to NodeBB v4.3 + New Features

PySide6 D-Bus Signal Interface Not Emitting or Discoverable

Scheduled Pinned Locked Moved Qt for Python
2 Posts 2 Posters 232 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    tolland
    wrote on last edited by tolland
    #1

    I'm building a PySide6 desktop app that uses QDBusConnection to expose a D-Bus interface with both methods and signals.
    ✅ Methods work:

    • Registering an object with QDBusConnection.registerObject(...) allows D-Bus method calls (e.g. ping()) to show up and function correctly.

      They appear in tools like qdbusviewer and respond as expected.

    ❌ But signals fail in two distinct scenarios:

    Case 1: Registering a plain QObject with ExportAllSignals

    I register it using:

    conn.registerObject("/org/example", obj, QDBusConnection.ExportAllSlots | QDBusConnection.ExportAllSignals)
    

    The signal does appear in dbus-monitor, but:

    • It uses a fallback interface name like local.myapp.module.MyObject (i.e. from Python module).

    • It has no bus name set in the dbus-monitor output.

    • It’s not filterable by interface name (e.g. interface='org.example.MyInterface') — so subscribers don’t catch it unless they match on path only.

    Attempts to override __module__ and __qualname__ only change the string in the signal, but do not fix this interface mismatch.

    I attach case1 which reproduces that problem

    import sys
    from PySide6.QtCore import QObject, Signal, QTimer
    from PySide6.QtWidgets import QApplication
    from PySide6.QtDBus import QDBusConnection
    import signal
    
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    
    
    class MyObject(QObject):
        my_signal = Signal(str)
    
        def __init__(self):
            super().__init__()
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.send_signal)
            self.timer.start(1000)
    
        def send_signal(self):
            print("Emitting signal...")
            self.my_signal.emit("hello from D-Bus")
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        obj = MyObject()
    
        conn = QDBusConnection.sessionBus()
        if not conn.registerService("org.example.TestApp"):
            print("❌ Failed to register service")
            sys.exit(1)
    
        flags = QDBusConnection.RegisterOption.ExportAllSignals
        if not conn.registerObject(
            "/org/example/TestObject",
            "org.example.interface",
            obj,
            flags,
        ):
            print("❌ Failed to register object")
            sys.exit(1)
    
        print("✅ Service and object registered. Use `dbus-monitor` to observe.")
        sys.exit(app.exec())
    

    running it like so:

    $ python scripts/case1.py
    ✅ Service and object registered. Use `dbus-monitor` to observe.
    Emitting signal...
    Emitting signal...
    Emitting signal...
    Emitting signal...
    

    we see the signal through introspection:

    [~] $ qdbus -h org.example.TestApp /org/example/TestObject
    signal void org.example.interface.my_signal(QString)
    method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
    method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
    signal void org.freedesktop.DBus.Properties.PropertiesChanged(QString interface_name, QVariantMap changed_properties, QStringList invalidated_properties)
    method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
    method QString org.freedesktop.DBus.Introspectable.Introspect()
    method QString org.freedesktop.DBus.Peer.GetMachineId()
    method void org.freedesktop.DBus.Peer.Ping()
    

    signal shows as follows:

    C
    [~] $ dbus-monitor "type='signal'" --profile | grep example
    sig     1742977053.198865       16      :1.1200 <none>  /org/example/TestObject local.py.case1.MyObject        my_signal
    sig     1742977054.148935       17      :1.1200 <none>  /org/example/TestObject local.py.case1.MyObject        my_signal
    sig     1742977055.111065       18      :1.1200 <none>  /org/example/TestObject local.py.case1.MyObject        my_signal
    

    It’s not filterable by interface name (e.g. interface='org.example.MyInterface') — so subscribers don’t catch it unless they match on path only.

    dbus-next won't allow attaching to the empty dbus service name. So its not that useful, though i guess some exhaustive searching all services and paths for interface.

    Case 2: Using QDBusAbstractAdaptor

    • I create an adaptor class subclassing QDBusAbstractAdaptor, define Signal attributes and @Slot methods.

    case2.py

    # case2_adaptor_signal_fail.py
    import sys
    import signal
    from PySide6.QtCore import QObject, Signal, Slot, QTimer
    from PySide6.QtWidgets import QApplication
    from PySide6.QtDBus import QDBusConnection, QDBusAbstractAdaptor
    
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    
    SERVICE_NAME = "org.example.TestApp"
    OBJECT_PATH = "/org/example/TestObject"
    INTERFACE_NAME = "org.example.interface"
    
    
    class BackendObject(QObject):
        def __init__(self):
            super().__init__()
            self.setObjectName("BackendObject")
    
    
    class MyAdaptor(QDBusAbstractAdaptor):
        appLaunched = Signal(str)
    
        def __init__(self, parent: QObject):
            super().__init__(parent)
            self.setAutoRelaySignals(True)
            self._timer = QTimer(self)
            self._timer.timeout.connect(self.emit_signal)
            self._timer.start(1000)
    
        @Slot()
        def emit_signal(self):
            print("🚨 Emitting appLaunched...")
            self.appLaunched.emit("hello from QDBusAbstractAdaptor")
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        backend = BackendObject()
        adaptor = MyAdaptor(backend)
    
        conn = QDBusConnection.sessionBus()
        if not conn.registerService(SERVICE_NAME):
            print("❌ Failed to register service")
            sys.exit(1)
    
        flags = QDBusConnection.RegisterOption.ExportAllSignals
        if not conn.registerObject(
            OBJECT_PATH,
            "org.example.interface",
            adaptor,
            flags,
        ):
            print("❌ Failed to register object")
            sys.exit(1)
    
        print(f"✅ Running at {SERVICE_NAME} {OBJECT_PATH}")
        sys.exit(app.exec())
    
    
    • I register the adaptor on a parent QObject and register the parent using:

      conn.registerObject("/org/example", interface, parent, QDBusConnection.ExportAdaptors)

    In this case:

    Introspection works — signals and methods appear in qdbusviewer and under the correct org.example.MyInterface name.

    [~] $ qdbus -h org.example.TestApp /org/example/TestObject
    signal void org.example.interface.appLaunched(QString)
    method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
    method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
    signal void org.freedesktop.DBus.Properties.PropertiesChanged(QString interface_name, QVariantMap changed_properties, QStringList invalidated_properties)
    method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
    method QString org.freedesktop.DBus.Introspectable.Introspect()
    method QString org.freedesktop.DBus.Peer.GetMachineId()
    method void org.freedesktop.DBus.Peer.Ping()
    

    But when I emit the signal from the adaptor using self.appLaunched.emit("Hello"), nothing appears on the D-Bus (not even in dbus-monitor).

    $ python scripts/case2.py
    ✅ Running at org.example.TestApp /org/example/TestObject
    🚨 Emitting appLaunched...
    🚨 Emitting appLaunched...
    🚨 Emitting appLaunched...
    🚨 Emitting appLaunched...
    🚨 Emitting appLaunched...
    🚨 Emitting appLaunched...
    

    nothing on the dbus-monitor

    [~] $ dbus-monitor "type='signal'" --profile | grep example
    

    Things tried so far:

    • [OK] QObject registered directly -> Signal appears on bus, but messy interface name (e.g. local.module.ClassName) and no bus_name
    • [FAIL] QDBusAbstractAdaptor used -> Interface visible in qdbusviewer, but signals never appear on dbus-monitor
    • [FAIL] Adaptor registered directly -> Nothing works; introspection and signals both fail
    • [FAIL] adaptor.emit() on adaptor -> No effect on D-Bus (signal doesn’t show up)
    • [FAIL] setAutoRelaySignals(True) used -> No help; signal still doesn’t emit on D-Bus
    • [FAIL] setting __classinfo__ = [("D-Bus Interface", "org.example.interface")] on adaptor and QObject
    • [FAIL] setting BackendObject.__module__ = "org.example.interface"
    • [FAIL] setting BackendObject.__qualname__ = "Interface"
    1 Reply Last reply
    0
    • T tolland marked this topic as a regular topic on
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Thanks for the detailed post and sorry I can't help you directly.
      Things that would help further:

      • which version of PySide6 are you using ?
      • which Linux distribution are you running ?
      • which version of DBus do you have ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved