2012-07-31 37 views
1

我想獲得一些使用PyQt4,特別是QtDBus在DBus上運行的基本代碼。我正在使用PyQt4的Python3版本。我已經得到了我想要在Qt(C++)上運行的代碼,但我想獲得僅使用Python運行的類似代碼。我想在其他Python代碼中調用DBus上的方法,信號/插槽和屬性。如何使用QDBusAbstractAdaptor和PyQt4公開DBus上的方法和屬性?

在Qt中,您使用Q_CLASSINFO宏/函數來執行DBus內省。雖然我已經拉入了Q_CLASSINFO方法,但我無法讓它產生相同類型的功能。據我所知,Q_CLASSINFO方法中沒有文檔,所以我不確定是否有其他方法。使用D-Feet我可以清楚地看到沒有方法自動曝光,所以我有點卡住了。

這是我到目前爲止。

from PyQt4 import QtDBus 
from PyQt4.QtCore import QCoreApplication, QObject, Q_CLASSINFO, pyqtSlot, pyqtProperty 
from PyQt4.QtDBus import QDBusConnection, QDBusAbstractAdaptor 

SERVICE = 'com.home.dbus' 

class MyServer(QObject): 


    def __init__(self): 
     QObject.__init__(self) 
     self.__dbusAdaptor = ServerAdaptor(self) 

    def close(self): 
     pass 

    def echo(self, value): 
     echoed = 'Received {0}'.format(value) 
     return echoed 

    def name(self): 
     return 'myname' 

    def dbus_adaptor(self): 
     return self.__dbusAdaptor 

class ServerAdaptor(QDBusAbstractAdaptor): 
    """ This provides the DBus adaptor to the outside world""" 

    def __init__(self, parent): 
     super().__init__(parent) 
     self.__parent = parent 
     Q_CLASSINFO("D-Bus Introspection", 
     " <interface name=\"com.home.dbus\">\n" 
     " <method name=\"name\">\n" 
     "  <arg direction=\"out\" type=\"s\" name=\"name\"/>\n" 
     " </method>\n" 
     " <method name=\"echo\">\n" 
     "  <arg direction=\"in\" type=\"s\" name=\"phrase\"/>\n" 
     "  <arg directory=\"out\" type=\"s\" name=\"echoed\"/>\n" 
     " </method>\n" 
     " </interface>\n") 

    def close(self): 
     parent.close() 

    def echo(self, value): 
     return parent.echo(value) 

    def name(self): 
     return parent.name 

def start(): 
    app = QCoreApplication([]) 
    if QDBusConnection.sessionBus().isConnected() == False: 
     print('Cannot connect to D-Bus session bus') 
     return 
    print('Starting') 
    server = MyServer() 
    if not QDBusConnection.sessionBus().registerService(SERVICE): 
     print('Unable to register service name') 
     return 
    if not QDBusConnection.sessionBus().registerObject('/mydbus', server.dbus_adaptor): 
     print('Unable to register object at service path') 
     return 
    app.exec(); 
    print('Exited') 

if __name__ == '__main__': 
    start() 

雖然我真的很喜歡使用QtDBus在C++中,因爲我想如何構建我的這個大項目,我真的需要通過的DBus訪問的對象要寫入Python3。

回答

4

你的程序有幾個問題。我建議看看最新的PyQt源碼的remotecontrolledcarpingpong例子,它們非常有幫助。需要注意的要點是:

  • 你應該通過一個MyServer實例(不ServerAdaptor)到registerObject()
  • 添加pyqtSlot()裝飾你希望通過揭露功能d總線
  • 呼叫Q_CLASSINFO()頂部適配器類的,不在其__init__()功能
  • 還設置了「d-總線接口」使用Q_CLASSINFO()
  • 你反省XML包含一個錯字(「直銷保守黨」而不是 '方向')

這裏是一個精簡的例子,對我的作品(Python的3.2.3/4.8.2的Qt/PyQt的4.9.4):

from PyQt4 import QtDBus 
from PyQt4.QtCore import (QCoreApplication, QObject, Q_CLASSINFO, pyqtSlot, 
          pyqtProperty) 
from PyQt4.QtDBus import QDBusConnection, QDBusAbstractAdaptor 

class MyServer(QObject): 

    def __init__(self): 
     QObject.__init__(self) 
     self.__dbusAdaptor = ServerAdaptor(self) 
     self.__name = 'myname' 

    def echo(self, value): 
     return'Received: {0}'.format(value) 

    @property 
    def name(self): 
     return self.__name 

    @name.setter 
    def name(self, value): 
     self.__name = value 


class ServerAdaptor(QDBusAbstractAdaptor): 
    """ This provides the DBus adaptor to the outside world""" 

    Q_CLASSINFO("D-Bus Interface", "com.home.dbus") 
    Q_CLASSINFO("D-Bus Introspection", 
    ' <interface name="com.home.dbus">\n' 
    ' <property name="name" type="s" access="readwrite"/>\n' 
    ' <method name="echo">\n' 
    '  <arg direction="in" type="s" name="phrase"/>\n' 
    '  <arg direction="out" type="s" name="echoed"/>\n' 
    ' </method>\n' 
    ' </interface>\n') 

    def __init__(self, parent): 
     super().__init__(parent) 

    @pyqtSlot(str, result=str) 
    def echo(self, phrase): 
     return self.parent().echo(phrase) 

    @pyqtProperty(str) 
    def name(self): 
     return self.parent().name 

    @name.setter 
    def name(self, value): 
     self.parent().name = value 

def start(): 
    app = QCoreApplication([]) 
    bus = QDBusConnection.sessionBus() 
    server = MyServer() 
    bus.registerObject('/mydbus', server) 
    bus.registerService('com.home.dbus') 
    app.exec() 

if __name__ == '__main__': 
    start() 
+0

真棒。謝謝您的幫助!正是我想要的。我發現QT的例子很好地在QT中解釋它,但在PyQT中沒有。那麼,只要Q_CLASSINFO具有屬性節點,這些屬性的工作方式是否與暴露自己一樣? (並使用pyProperties或任何屬性)。我需要做的最後一件事就是嘗試使用Windows DBus端口並將其發送出去......然後我用火做飯。 =) – Mike 2012-08-03 01:18:58

+0

是的,性能工作非常符合您的預期。我修改了我的例子,使'name'屬性。你能繼續並接受我的回答嗎? : - } – evadeflow 2012-08-03 17:00:34

+0

對不起!公認。 – Mike 2012-08-05 01:41:14