1. 程式人生 > >Qt高級——QtDBus快速入門

Qt高級——QtDBus快速入門

QtDBus 快速入門

Qt高級——QtDBus快速入門

一、QtDBus簡介

QtDBus是一個使用D-Bus協議進行進程間通信的僅在Unix運行的庫,是對D-Bus底層API的封裝實現。
QtDBus模塊提供了使用Qt信號槽機制擴展的接口。要使用QtDBus模塊,需要在代碼中加入以下代碼:

#include <QtDBus>

如果使用qmake構建程序,需要在工程文件中增加下列代碼來鏈接QtDBus庫:

QT += qdbus

二、QtDBus類型系統

1、QtDBus類型系統簡介

D-Bus有一種基於幾種原生與在數組和結構中的原生類型組成的復合類型的擴展類型系統。QtDBus模塊通過QDBusArgument類實現了類型系統,允許用戶通過總線發送和接收每一種C++類型。

2、原生類型

QtDBus通過QDBusArgument支持原生類型,不需要特殊的定制。

Qt類型                                     D-Bus類型
uchar                                        BYTE
bool                                          BOOLEAN
short                                         INT16
ushort                                       UINT16
int                                             INT32
uint                                           UINT32
qlonglong                                 INT64
qulonglong                               UINT64
double                                      DOUBLE
QString                                    STRING
QDBusVariant                          VARIANT
QDBusObjectPath                   OBJECT_PATH
QDBusSignature                      SIGNATURE

除了原生類型,QDBusArgument也支持在Qt應用中廣泛使用的兩種非原生類型,QStringList和QByteArray。

3、復合類型

D-Bus指定由原生類型聚合而成的三種復合類型:ARRAY、STRUCT和 maps/dictionaries。ARRAY零個或多個相同元素的集合,STRUCT是由不同類型的固定數量的元素組成的集合,Maps or dictionaries是元素對的數組,一個map中可以有零個或多個元素。

4、擴展類型系統

為了在QtDBus模塊使用自定義類型,自定義類性必須使用Q_DECLARE_METATYPE()聲明為Qt元類型,使用qDBusRegisterMetaType()函數註冊。流操作符會被註冊系統自動找到。

QtDBus模塊為Qt容器類使用數組和map提供了模板特化,例如QMap和QList,不必實現流操作符函數。對於其它的類型,流操作符必須顯示實現。

5、類型系統使用

QtDBus定義的所有類型能用於通過總線發送和接收消息。不能使用上述類型之外的任何類型,包括typedefs定義的列表類型,如

QList<QVariant>`和`QMap< QString,QVariant>

三、QtDBus常用類

1、QDBusMessage

QDBusMessage類表示D-Bus總線發送或接收的一個消息。
QDBusMessage對象代表總線上四種消息類型中的一種,四種消息類型如下:
A、Method calls
B、Method return values
C、Signal emissions
D、Error codes
可以使用靜態函數createError()、createMethodCall()、createSignal()創建消息。使用QDBusConnection::send() 函數發送消息。

2、QDBusConnection

QDBusConnection代表到D-Bus總線的一個連接,是一個D-Bus會話的起始點。通過QDBusConnection連接對象,可以訪問遠程對象、接口,連接遠程信號到本地槽函數,註冊對象等。
D-Bus連接通過connectToBus()函數創建,connectToBus()函數會創建一個到總線服務端的連接,完成初始化工作,並關聯一個連接名到連接。
使用disconnectFromBus()函數會斷開連接。一旦斷開連接後,調用connectToBus()函數將不會重建連接,必須創建新的QDBusConnection實例。
作為兩種最常用總線類型的輔助,sessionBus()和systemBus()函數分別創建到會話在總線和系統總線的連接並返回,會在初次使用時打開,在QCoreApplication析構函數調用時斷開。
D-Bus支持點對點通信,不必使用總線服務。兩個應用程序可以直接交流和交換消息。可以通過傳遞一個地址到connectToBus()函數實現。
QDBusConnection connectToBus(BusType type, const QString & name)
打開一個type類型的連接,並關聯name連接名,返回關聯本連接的QDBusConnection對象。
QDBusConnection connectToBus(const QString & address, const QString & name)
打開一個地址為address的私有總線,並關聯name連接名,返回關聯本連接的QDBusConnection對象。
QDBusConnection connectToPeer(const QString & address, const QString & name)
打開一個點對點的連接到address地址,並關聯name連接名,返回關聯本連接的QDBusConnection對象。
void disconnectFromBus(const QString & name)
關閉名為name的總線連接
void disconnectFromPeer(const QString & name)
關閉名為name的對等連接
QByteArray localMachineId()
返回一個D-Bus總線系統知道的本機ID
QDBusConnection sender()
返回發送信號的連接
QDBusConnection sessionBus()
返回一個打開到session總線的QDBusConnection對象
QDBusConnection systemBus()
返回一個打開到system總線的QDBusConnection對象
QDBusPendingCall asyncCall(const QDBusMessage & message, int timeout = -1)const
發送message消息到連接,並立即返回。本函數只支持method調用。返回一個用於追蹤應答的QDBusPendingCall對象。
QDBusMessage call(const QDBusMessage & message, QDBus::CallMode mode = QDBus::Block, int timeout = -1 ) const
通過本連接發送消息message,並且阻塞,等待應答。
bool registerObject(const QString & path, QObject * object, RegisterOptions options = ExportAdaptors)
註冊object對象到路徑path,options選項指定由多少對象會被暴露到D-Bus總線,如果註冊成功,返回true。
bool registerService(const QString & serviceName)
試圖在D-Bus總線上註冊serviceName服務,如果註冊成功,返回true;如果名字已經在其它應用被註冊,則註冊失敗。

3、QDBusInterface

QDBusInterface是遠程對象接口的代理。
QDBusInterface是一種通用的訪問器類,用於調用遠程對象,連接到遠程對象導出的信號,獲取/設置遠程屬性的值。當沒有生成表示遠程接口的生成代碼時時,QDBusInterface類對遠程對象的動態訪問非常有用。
調用通常是通過使用call()函數來實現,call函數構造消息,通過總線發送消息,等待應答並解碼應答。信號使用QObject::connect()函數進行連接。最終,使用QObject::property()和QObject::setProperty()函數對屬性進行訪問。

4、QDBusReply

QDBusReply類用於存儲對遠程對象的方法調用的應答。
一個QDBusReply對象是方法調用的應答QDBusMessage對象的一個子集。QDBusReply對象只包含第一個輸出參數或錯誤代碼,並由QDBusInterface派生類使用,以允許將錯誤代碼返回為函數的返回參數。

QDBusReply<QString> reply = interface->call("RemoteMethod");
 if (reply.isValid())
     // use the returned value
     useValue(reply.value());
 else
     // call failed. Show an error condition.
     showError(reply.error());

對於沒有輸出參數或返回值的遠程調用,使用isValid()函數測試應答是否成功。

5、QDBusAbstractAdaptor

QDBusAbstractAdaptor類使用D-Bus Adaptor基類。
QDBusAbstractAdaptor類是用於使用D-Bus向外部提供接口的所有對象的起點。可以通過將一個或多個派生自QDBusAbstractAdaptor的類附加到一個普通QObject對象上,使用QDBusConnection::registerObject註冊QObject對象可以實現。QDBusAbstractAdaptor是一個輕量級封裝,主要用於中繼調用實際對象及其信號。
每個QDBusAbstractAdaptor派生類都應該使用類定義中的Q_CLASSINFO宏來定義D-Bus接口。註意,這種方式只有一個接口可以暴露。
QDBusAbstractAdaptor使用了信號、槽、屬性的標準QObject機制來決定哪些信號、槽、屬性被暴露到總線。任何QDBusAbstractAdaptor派生類發送的信號通過任何D-Bus連接自動中繼到註冊的對象上。
QDBusAbstractAdaptor派生類對象必須使用new創建在堆上,不必由用戶刪除。

6、QDBusAbstractInterface

QDBusAbstractInterface是QtDBus模塊中允許訪問遠程接口的所有D-Bus接口的基類。
自動生成的代碼類也繼承自QDBusAbstractInterface,此描述的所有方法在生成的代碼中也有效。除了此處的描述,生成代碼類為遠程方法提供了成員函數,允許在編譯時檢查正確參數和返回值,以及匹配的屬性類型和匹配的信號參數。

QDBusPendingCall asyncCall(const QString & method, 
                           const QVariant & arg1 = QVariant(), 
                           const QVariant & arg2 = QVariant(), 
                           const QVariant & arg3 = QVariant(), 
                           const QVariant & arg4 = QVariant(),
                           const QVariant & arg5 = QVariant(), 
                           const QVariant & arg6 = QVariant(), 
                           const QVariant & arg7 = QVariant(), 
                           const QVariant & arg8 = QVariant())

調用本接口中的method方法,傳遞參數到遠程的method。
要調用的參數會通過D-Bus輸入參數傳遞到遠程方法,返回的QDBusPendingCall對象用於定義應答信息。
本函數最多有8個參數,如果參數多於8個,或是傳遞可變數量的參數,使用asyncCallWithArgumentList()函數。

QString value = retrieveValue();
QDBusPendingCall pcall = interface->asyncCall(QLatin1String("Process"), value);

QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);

QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
                 this, SLOT(callFinishedSlot(QDBusPendingCallWatcher*)));

7、QDBusArgument

QDBusArgument類用於整理和分發D-Bus參數。QDBusArgument用於通過D-Bus發送參數到遠程應用,並接收返回。
QDBusArgument是QtDBus類型系統的核心類,QtDBus類型系統用於解析和原生類型。復合類型可以通過在數組、詞典或結構中使用一個或多個原生類型創建。
下列代碼展示了使用QtDBus類型系統構造的包含一個整數和字符串的結構。

struct MyStructure
 {
     int count;
     QString name;
 };
 Q_DECLARE_METATYPE(MyStructure)
// Marshall the MyStructure data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const MyStructure &mystruct)
{
    argument.beginStructure();
    argument << mystruct.count << mystruct.name;
    argument.endStructure();
    return argument;
}

// Retrieve the MyStructure data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, MyStructure &mystruct)
{
    argument.beginStructure();
    argument >> mystruct.count >> mystruct.name;
    argument.endStructure();
    return argument;
}

在QDBusArgument使用這個結構前,必須使用qDBusRegisterMetaType()函數進行註冊。因此,在程序中應該則增加如下代碼:
qDBusRegisterMetaType&lt;MyStructure&gt;();
一旦註冊,類型可以在呼出方法調用(QDBusAbstractInterface::call())、來自註冊對象的信號發射或來自遠程應用的傳入調用。

8、QDBusConnectionInterface

QDBusConnectionInterface類提供了對D-Bus總線服務的訪問。
D-Bus總線服務端中提供了一個特殊的接口org.freedesktop.DBus,允許客戶端運行訪問總線的某些屬性,例如當前連接的客戶端列表,QDBusConnectionInterface類提供對org.freedesktop.DBus接口的訪問。
本類中最常用的是使用registerService()和unregisterService()在總線上註冊和註銷服務名。
QDBusConnectionInterface類定義四個信號,在總線上有服務狀態變化時發送。

void callWithCallbackFailed(const QDBusError & error, const QDBusMessage & call)
void serviceOwnerChanged(const QString & name, const QString & oldOwner, const QString & newOwner)
void serviceRegistered(const QString & serviceName)
void serviceUnregistered(const QString & serviceName)

9、QDBusVariant

QDBusVariant類使程序員能夠識別由D-Bus類型系統提供的Variant類型。一個使用整數、D-Bus變體類型和字符串作為參數的D-Bus函數可以使用如下的參數列表調用。

QList<QVariant> arguments;
arguments << QVariant(42) << QVariant::fromValue(QDBusVariant(43)) << QVariant("hello");
myDBusMessage.setArguments(arguments);

當D-Bus函數返回一個D-Bus變體類型時,可以使用如下方法獲取:

// call a D-Bus function that returns a D-Bus variant
QVariant v = callMyDBusFunction();
// retrieve the D-Bus variant
QDBusVariant dbusVariant = qvariant_cast<QDBusVariant>(v);
// retrieve the actual value stored in the D-Bus variant
QVariant result = dbusVariant.variant();

QDBusVariant中的QVariant需要區分一個正常的D-Bus值和一個QDBusVariant中的值。

四、QtDBus工具

1、qdbusviewer

qdbusviewer用於查看D-Bus總線上的服務、對象、接口以及接口的method。使用方法直接在命令行執行:qdbusviewer
技術分享圖片

2、qdbuscpp2xml

qdbuscpp2xml會解析QObject派生類的C++頭文件或是源文件,生成D-Bus的內省xml文件。qdbuscpp2xml 會區分函數的輸入輸出,如果參數聲明為const則會是輸入,否則可能會被當作輸出。
qdbuscpp2xml使用語法如下:
qdbuscpp2xml [options...] [files...]
Options參數如下:
-p|-s|-m:只解析腳本化的屬性、信號、方法(槽函數)
-P|-S|-M:解析所有的屬性、信號、方法(槽函數)
-a:輸出所有的腳本化內容,等價於-psm
-A:輸出所有的內容,等價於-PSM
-o filename:輸出內容到filename文件
解析所有的方法輸出到com.scorpio.test.xml文件命令如下:
qdbuscpp2xml -M test.h -o com.scorpio.test.xml

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="com.scorpio.test.value">
    <method name="maxValue">
      <arg type="i" direction="out"/>
    </method>
    <method name="minValue">
      <arg type="i" direction="out"/>
    </method>
    <method name="value">
      <arg type="i" direction="out"/>
    </method>
    <method name="setValue">
      <arg name="value" type="i" direction="in"/>
    </method>
  </interface>
</node>

3、qdbusxml2cpp

qdbusxml2cpp根據輸入文件中定義的接口,生成C++實現代碼。
qdbusxml2cpp可以輔助自動生成繼承於QDBusAbstractAdaptor和QDBusAbstractInterface兩個類的實現代碼,用於進程通信服務端和客戶端,簡化了開發者的代碼設計。
qdbusxml2cpp使用語法如下:
qdbusxml2cpp [options...] [xml-or-xml-file] [interfaces...]
Options參數如下:
-a filename:輸出Adaptor代碼到filename
-c classname:使用classname作為生成類的類名
-i filename:增加#include到輸出
-l classname:當生成Adaptor代碼時,使用classname作為父類
-m:在cpp文件中包含 #include "filename.moc"語句
-N:不使用名稱空間
-p filename:生成Proxy代碼到filename文件
解析com.scorpio.test.xml文件,生成Adaptor類ValueAdaptor,文件名稱為valueAdaptor.h、valueAdaptor.cpp命令行如下:
qdbusxml2cpp com.scorpio.test.xml -i test.h -a valueAdaptor
解析com.scorpio.test.xml文件,生成Proxy類ComScorpioTestValueInterface,文件名稱為testInterface.h、testInterface.cpp命令行如下:
qdbusxml2cpp com.scorpio.test.xml -p testInterface

五、QtDBus編程

1、創建服務並註冊對象

test.h文件:

#ifndef TEST_H
#define TEST_H
#include <QObject>

class test: public QObject
{
    Q_OBJECT
    //定義Interface名稱為com.scorpio.test.value
    Q_CLASSINFO("D-Bus Interface", "com.scorpio.test.value")
public:
    test(int value);

public slots:
    int maxValue();
    int minValue();
    int value();
private:
    int m_value;
};

#endif // TEST_H

test.cpp文件:

#include "test.h"

test::test(int value)
{
    m_value = value;
}

int test::maxValue()
{
    return 100;
}
int test::minValue()
{
    return 0;
}
int test::value()
{
    return m_value;
}

main.cpp文件:

#include <QCoreApplication>
#include <QDBusConnection>
#include <QDebug>
#include <QDBusError>
#include "test.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //建立到session bus的連接
    QDBusConnection connection = QDBusConnection::sessionBus();
    //在session bus上註冊名為com.scorpio.test的服務
    if(!connection.registerService("com.scorpio.test"))
    {
        qDebug() << "error:" << connection.lastError().message();
        exit(-1);
    }
    test object(60);
    //註冊名為/test/objects的對象,把類Object所有槽函數導出為object的method
    connection.registerObject("/test/objects", &object,QDBusConnection::ExportAllSlots);

    return a.exec();
}

啟動程序後,在命令行打開qdbusviewer,查看session bus。
技術分享圖片
雙擊Method方法會調用該方法。

2、通過QDBusMessage訪問Service

確保com.scorpio.test服務運行在總線上。
編寫一個控制臺程序,使用消息訪問com.scorpio.test服務。

#include <QCoreApplication>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //構造一個method_call消息,服務名稱為:com.scorpio.test,對象路徑為:/test/objects
    //接口名稱為com.scorpio.test.value,method名稱為value
    QDBusMessage message = QDBusMessage::createMethodCall("com.scorpio.test",
                           "/test/objects",
                           "com.scorpio.test.value",
                           "value");
    //發送消息
    QDBusMessage response = QDBusConnection::sessionBus().call(message);
    //判斷method是否被正確返回
    if (response.type() == QDBusMessage::ReplyMessage)
    {
        //從返回參數獲取返回值
        int value = response.arguments().takeFirst().toInt();
        qDebug() << QString("value =  %1").arg(value);
    }
    else
    {
        qDebug() << "value method called failed!";
    }

    return a.exec();
}

3、通過QDBusInterface?訪問Service

編寫一個控制臺程序,使用接口訪問com.scorpio.test服務。

#include <QCoreApplication>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDBusReply>
#include <QDBusInterface>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 創建QDBusInterface接口
    QDBusInterface interface("com.scorpio.test", "/test/objects",
                             "com.scorpio.test.value",
                             QDBusConnection::sessionBus());
    if (!interface.isValid())
    {
        qDebug() << qPrintable(QDBusConnection::sessionBus().lastError().message());
        exit(1);
    }
    //調用遠程的value方法
    QDBusReply<int> reply = interface.call("value");
    if (reply.isValid())
    {
        int value = reply.value();
        qDebug() << QString("value =  %1").arg(value);
    }
    else
    {
        qDebug() << "value method called failed!";
    }

    return a.exec();
}

4、從D-Bus XML自動生成Proxy類

Proxy Object提供了一種更加直觀的方式來訪問Service,如同調用本地對象的方法一樣。?
生成Proxy類的流程如下:
A、使用工具qdbuscpp2xml從object.h生成XML文件;
qdbuscpp2xml -M test.h -o com.scorpio.test.xml

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="com.scorpio.test.value">
    <method name="maxValue">
      <arg type="i" direction="out"/>
    </method>
    <method name="minValue">
      <arg type="i" direction="out"/>
    </method>
    <method name="value">
      <arg type="i" direction="out"/>
    </method>
  </interface>
</node>

B、使用工具qdbusxml2cpp從XML文件生成繼承自QDBusInterface的類
qdbusxml2cpp com.scorpio.test.xml -p valueInterface
生成兩個文件:valueInterface.cpp和valueInterface.h
valueInterface.h文件:

/*
 * This file was generated by qdbusxml2cpp version 0.7
 * Command line was: qdbusxml2cpp com.scorpio.test.xml -p testInterface
 *
 * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 *
 * This is an auto-generated file.
 * Do not edit! All changes made to it will be lost.
 */

#ifndef TESTINTERFACE_H_1526737677
#define TESTINTERFACE_H_1526737677

#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>

/*
 * Proxy class for interface com.scorpio.test.value
 */
class ComScorpioTestValueInterface: public QDBusAbstractInterface
{
    Q_OBJECT
public:
    static inline const char *staticInterfaceName()
    { return "com.scorpio.test.value"; }

public:
    ComScorpioTestValueInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0);

    ~ComScorpioTestValueInterface();

public Q_SLOTS: // METHODS
    inline QDBusPendingReply<int> maxValue()
    {
        QList<QVariant> argumentList;
        return asyncCallWithArgumentList(QLatin1String("maxValue"), argumentList);
    }

    inline QDBusPendingReply<int> minValue()
    {
        QList<QVariant> argumentList;
        return asyncCallWithArgumentList(QLatin1String("minValue"), argumentList);
    }

    inline QDBusPendingReply<int> value()
    {
        QList<QVariant> argumentList;
        return asyncCallWithArgumentList(QLatin1String("value"), argumentList);
    }

Q_SIGNALS: // SIGNALS
};

namespace com {
  namespace scorpio {
    namespace test {
      typedef ::ComScorpioTestValueInterface value;
    }
  }
}
#endif

valueInterface.cpp文件:

/*
 * This file was generated by qdbusxml2cpp version 0.7
 * Command line was: qdbusxml2cpp com.scorpio.test.xml -p testInterface
 *
 * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 *
 * This is an auto-generated file.
 * This file may have been hand-edited. Look for HAND-EDIT comments
 * before re-generating it.
 */

#include "testInterface.h"

/*
 * Implementation of interface class ComScorpioTestValueInterface
 */

ComScorpioTestValueInterface::ComScorpioTestValueInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
    : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}

ComScorpioTestValueInterface::~ComScorpioTestValueInterface()
{
}

調用Proxy類訪問Service如下:

#include <QCoreApplication>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDBusReply>
#include <QDBusInterface>
#include <QDebug>
#include "testInterface.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // 初始化自動生成的Proxy類com::scorpio::test::value
    com::scorpio::test::value test("com.scorpio.test",
                                   "/test/objects",
                                   QDBusConnection::sessionBus());
    // 調用value方法
    QDBusPendingReply<int> reply = test.value();
    //qdbusxml2cpp生成的Proxy類是采用異步的方式來傳遞Message,
    //所以需要調用waitForFinished來等到Message執行完成
    reply.waitForFinished();
    if (reply.isValid())
    {
        int value = reply.value();
        qDebug() << QString("value =  %1").arg(value);
    }
    else
    {
        qDebug() << "value method called failed!";
    }

    return a.exec();
}

5、使用Adapter註冊Object

可以直接把test類註冊為消息總線上的一個Object,但QT4不推薦。QT4推薦使用Adapter來註冊Object。
大多數情況下,可能只需要把自定義的類裏的方法有選擇的發布到消息總線上,使用Adapter可以很方便的實現選擇性發布。
生成Adapter類的流程如下:
A、使用工具?qdbuscpp2xml從test.h生成XML文件
qdbuscpp2xml -M test.h -o com.scorpio.test.xml?
B、編輯com.scorpio.test.xml,選擇需要發布的method,不需要發布的刪除。
C、使用工具qdbusxml2cpp從XML文件生成繼承自QDBusInterface的類
qdbusxml2cpp com.scorpio.test.xml -i test.h -a valueAdaptor
生成兩個文件:valueAdaptor.cpp和valueAdaptor.h
valueAdaptor.h文件:

/*
 * This file was generated by qdbusxml2cpp version 0.7
 * Command line was: qdbusxml2cpp com.scorpio.test.xml -i test.h -a valueAdaptor
 *
 * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 *
 * This is an auto-generated file.
 * This file may have been hand-edited. Look for HAND-EDIT comments
 * before re-generating it.
 */

#ifndef VALUEADAPTOR_H_1526742670
#define VALUEADAPTOR_H_1526742670

#include <QtCore/QObject>
#include <QtDBus/QtDBus>
#include "test.h"
class QByteArray;
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
class QStringList;
class QVariant;

/*
 * Adaptor class for interface com.scorpio.test.value
 */
class ValueAdaptor: public QDBusAbstractAdaptor
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "com.scorpio.test.value")
    Q_CLASSINFO("D-Bus Introspection", ""
"  <interface name=\"com.scorpio.test.value\">\n"
"    <method name=\"maxValue\">\n"
"      <arg direction=\"out\" type=\"i\"/>\n"
"    </method>\n"
"    <method name=\"minValue\">\n"
"      <arg direction=\"out\" type=\"i\"/>\n"
"    </method>\n"
"  </interface>\n"
        "")
public:
    ValueAdaptor(QObject *parent);
    virtual ~ValueAdaptor();

public: // PROPERTIES
public Q_SLOTS: // METHODS
    int maxValue();
    int minValue();
Q_SIGNALS: // SIGNALS
};

#endif

valueAdaptor.cpp文件:

/*
 * This file was generated by qdbusxml2cpp version 0.7
 * Command line was: qdbusxml2cpp com.scorpio.test.xml -i test.h -a valueAdaptor
 *
 * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 *
 * This is an auto-generated file.
 * Do not edit! All changes made to it will be lost.
 */

#include "valueAdaptor.h"
#include <QtCore/QMetaObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>

/*
 * Implementation of adaptor class ValueAdaptor
 */

ValueAdaptor::ValueAdaptor(QObject *parent)
    : QDBusAbstractAdaptor(parent)
{
    // constructor
    setAutoRelaySignals(true);
}

ValueAdaptor::~ValueAdaptor()
{
    // destructor
}

int ValueAdaptor::maxValue()
{
    // handle method call com.scorpio.test.value.maxValue
    int out0;
    QMetaObject::invokeMethod(parent(), "maxValue", Q_RETURN_ARG(int, out0));
    return out0;
}

int ValueAdaptor::minValue()
{
    // handle method call com.scorpio.test.value.minValue
    int out0;
    QMetaObject::invokeMethod(parent(), "minValue", Q_RETURN_ARG(int, out0));
    return out0;
}

調用Adaptor類註冊Object對象如下:

#include <QCoreApplication>
#include <QDBusConnection>
#include <QDebug>
#include <QDBusError>
#include "test.h"
#include "valueAdaptor.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QDBusConnection connection = QDBusConnection::sessionBus();
    test object(60);
    //ValueAdaptor是qdbusxml2cpp生成的Adaptor類
    ValueAdaptor valueAdaptor(&object);
    if (!connection.registerService("com.scorpio.test"))
    {
        qDebug() << connection.lastError().message();
        exit(1);
    }
    connection.registerObject("/test/objects", &object);
    return a.exec();
}

使用qdbusviewer查看發布的method。
技術分享圖片

6、自動啟動Service

D-Bus系統提供了一種機制可以在訪問某個service時,自動把應用程序運行起來。
需要在/usr/share/dbus-1/services下面建立com.scorpio.test.service文件,文件的內容如下:

[D-BUS Service]
Name=com.scorpio.test
Exec=/path/to/scorpio/test

在訪問test的method前,不必手動運行應用程序。

Qt高級——QtDBus快速入門