記一下:來自https://blog.csdn.net/lvliang2008/article/details/6304003
1 概述
D-Bus是一種高級的進程間通信機制,它由freedesktop.org項目提供,使用GPL許可證發行。D-Bus最主要的用途是在Linux桌面環境爲進程提供通信,同時能將Linux桌面環境和Linux內核事件作爲消息傳遞到進程。D-Bus的主要概率爲總線,註冊後的進程可通過總線接收或傳遞消息,進程也可註冊後等待內核事件響應,例如等待網絡狀態的轉變或者計算機發出關機指令。目前,D-Bus已被大多數Linux發行版所採用,開發者可使用D-Bus實現各種複雜的進程間通信任務。
D-Bus是一個消息總線系統,其功能已涵蓋進程間通信的所有需求,並具備一些特殊的用途。D-Bus是三層架構的進程間通信系統,其中包括:
接口層:接口層由函數庫libdbus提供,進程可通過該庫使用D-Bus的能力。
總線層:總線層實際上是由D-Bus總線守護進程提供的。它在Linux系統啓動時運行,負責進程間的消息路由和傳遞,其中包括Linux內核和Linux桌面環境的消息傳遞。
包裝層:包裝層一系列基於特定應用程序框架的Wrapper庫。
在QT中的Dbus是使用的Dbus的包裝層libdbus-qt.
要查看Dbus總線上的服務和對象可以藉助d-feet 和qdbusviewer
要發送信號可以使用dbus-send,要查看Dbus上的消息流可以使用dbus-monitor
QT Dbus是在QT4.2中才引進到QT中來的,還有很多的地方不是很完善,在網上DBus的資料比較多,不過很多都是基入GTK的,基入QT的資料還比較的少,主要可以參考
D-Bus和QT4 (wwang's blog一蓑煙雨任平生)
http://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html
其他的DBus的基本資料可以參考:
DBus學習筆記(博客園)
http://dotnet.cnblogs.com/page/76759/?page=1
愷風的CSDN博客
http://blog.csdn.net/flowingflying/archive/2009/09/07/4527634.aspx
2 QT中Dbus的最簡單的用法
關於QT中的DBus的用法介紹的文章比較的少,網上只有這篇文章(國外的網站上可能有更多,只是沒有發現而已)和QT中的四個例子程序。
這個最簡單的用法是在使用中發現的,不需要在Dbus的守護進程上註冊服務和註冊對象。
註冊了對象後:對象中的導出的槽就可以供其他的客戶端來調用了。
註冊了服務後:對象就有了一個公共名,沒有註冊是隻有三個唯一名。
在發送端只需創建一個信號原後發送即可,
例如:
1) 創建QT的DBus信號
QDBusMessage msg =QDBusMessage::createSignal("/hotel/path", "hotel.interface", "checkIn");
2) 給信號賦值
msg<<this->ui->checkInlineEdit->text().toInt();
3) 發射信號
QDBusConnection::sessionBus().send(msg);
在接受端同樣只需要簡單的兩三步即可
1) 綁定信號
QDBusConnection::sessionBus().connect(QString(),QString(),"dbus.client. interface","Active",this,SLOT(ActiveEvent(int)));
2) 在槽中進行相關的處理
在ActiveEvent槽中執行你的應用程序需要對這個信號做出的反應即可。
這樣的使用在DBUS的守護進程中沒有服務,只有三個唯一名,沒有公共名,也沒有任何的信號、槽、屬性。
可以通過d-feet、 qdbusviewe來查看。
可以通過dbus-monitor監視信號發送過程
可以參考示例DBusSignalMethod中DBusServerDBusSignal和DBusClientDBusSignal
3 QT中DBus的常規用法
在以下這篇文章中已經很好的介紹了QT DBus的各種常規的用法了,在此就重複了,這種用法主要是在服務端,需要在DBus的守護進程上註冊對象和註冊服務,原後其他的客戶端就可以自由的調用了。
不過這種方式也有一個好處,調用是服務端的返回的參數就只發給調用的客戶端,是一對一的,不想上面的用信號的方式,信號的方式,發送的信號是一對多的。
D-Bus和QT4 (wwang's blog一蓑煙雨任平生)
http://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html
在也有幾個小的例子程序是根據D-Bus和QT4 (wwang's blog一蓑煙雨任平生)的例子改編的。
在常規用法中也分客戶端和服務端的,
客戶端有三種用法,服務端有兩個用法。
3.1 客戶端的用法1:使用QDBusMessage
可以參考實例DBusMessage中的DBusServer和DBusClient
1) 創建一個QDBusMessage的方法調用
a) QDBusMessage m = QDBusMessage::createMethodCall("hotel.server",
i. "/hotel/path",
ii. "hotel.interface",
iii. "checkIn");
2) 給方法傳遞參數
a) m<<this->ui->checkInlineEdit->text().toInt();
3) 調用方法
a) QDBusMessage response = QDBusConnection::sessionBus().call(m);
4) 判斷方法的返回值
if (response.type() == QDBusMessage::ReplyMessage) {
// QDBusMessage的arguments不僅可以用來存儲發送的參數,也用來存儲返回值;
// 這裏取得checkIn的返回值
int num_room = response.arguments().takeFirst().toInt();
qDebug("Got %d %s/n", num_room, (num_room > 1) ? "rooms" : "room");
} else
{
qDebug( "Check In fail!/n");
}
3.2客戶端的用法2:使用DBusInterface
可以參考實例DBusInterface中的DBusServer和DBusClientInterface
1) 創建一個QDBusInterface的實例
QDBusInterface iface( "hotel.server",
"/hotel/path",
"hotel.interface", QDBusConnection::sessionBus());
if (!iface.isValid()) {
qDebug() << qPrintable(QDBusConnection::sessionBus().lastError().message());
exit(1);
}
2) 傳遞參數
int num_room;
num_room= this->ui->checkInlineEdit->text().toInt();
3) 呼叫遠程的checkIn,參數爲num_room
QDBusReply<int> reply = iface.call("checkIn", num_room);
4) 判斷返回值
if (reply.isValid()) {
num_room = reply.value();
qDebug("Got %d %s/n", num_room, (num_room > 1) ? "rooms" : "room");
} else {
qDebug( "Check In fail!/n");
}
3.3 客戶端的用法3:使用DBusProxy
可以參考實例DBusProxy中的DBusClientProxy和DBusServer
DBusProxy可以使訪問更加方便,就像訪問本地類成員變量的方式訪問遠程的method
在使用這個類的時候要使用兩個工具
qdbuscpp2xml和qdbusxml2cpp
利用qdbuscpp2xml –M –S hotel.h –o hotel.xml
在利用qdbusxml2cpp hotel.xml –p hotelInterface
在客戶端的工程中添加這倆個文件。
1) 創建接口
a) hotel::interface myHotel("hotel.server",
a) "/hotel/path",
i. QDBusConnection::sessionBus());
2) 給參數賦值
i. int num_room;
ii. num_room= this->ui->checkInlineEdit->text().toInt();
3) 調用checkIn
a) QDBusPendingReply<int> reply = myHotel.checkIn(num_room);
4) 等待完成
a) reply.waitForFinished();
5) 判斷返回值
if (reply.isValid()) {
num_room = reply.value();
qDebug("Got %d %s/n", num_room, (num_room > 1) ? "rooms" : "room");
} else {
qDebug( "Check In fail!/n");
}
3.4服務端的用法1:直接註冊對象和服務
可以參考實例DBusMessage中的DBusServer
1) 創建連接
QDBusConnection bus = QDBusConnection::sessionBus();
// 在session bus上註冊名爲"com.test.hotel"的service
2) 註冊服務
if (!bus.registerService("hotel.server")) {
a) qDebug() << bus.lastError().message();
b) exit(1);
}
3) 註冊對象
if(! (bus.registerObject("/hotel/path", &my_hotel , QDBusConnection::ExportAllSlots)))
{
qDebug() << bus.lastError().message();
exit(1);
}
3.5 服務端的用法2:使用DBusAdapter
可以參考實例DBusAdapter中的DBusServerXML
QT4推薦使用Adapter來註冊Object。
很多情況下,我們可能只需要把我們定義的類裏的方法有選擇的發佈到Message Bus上,使用Adapter可以很方便的實現這種意圖
1) 創建連接
QDBusConnection bus = QDBusConnection::sessionBus();
// 在session bus上註冊名爲"com.test.hotel"的service
2) 註冊服務
if (!bus.registerService("hotel.server")) {
qDebug() << bus.lastError().message();
exit(1);
}
3) 創建Adaptor對象
myHotelAdaptor =new InterfaceAdaptor(&my_hotel);
4) 註冊對象
if(! (bus.registerObject("/hotel/path", &my_hotel ,QDBusConnection::ExportAllSlots)))
{
qDebug() << bus.lastError().message();
exit(1);
}
4 QT中Dbus的特殊的用法(使用QT的信號)
在使用QT一段時間後,大家也許對QT的信號與槽很熟悉了,再來了一個DBus的信號與槽,大家可能很容易混淆了,想直接使用QT的信號與槽?
這樣也是可以的,可以參照QT的例子程序 dbus-chat,中間就有這種用法的。
發射信號直接用QT的,綁定信號與槽也用QT的是不是很熟悉了。
具體的可以參考QT的實例dbus-chat
也可以參考實例QTSignalSlot中的DBusClientQTSignal和DBusServerQTSignal
發送信號端:
1 新建一個DBus服務
QDBusConnection bus = QDBusConnection::sessionBus();
2 註冊對象(註冊的時候必須註冊this,這樣this對象中的信號就可以直接發送到DBus上)
bus.registerObject("/hotel/path", this ,
QDBusConnection::ExportAllSlots|
QDBusConnection::ExportAllSignals);
接受信號端:
1 新建一個接口
myInterface= new hotel::interface(QString(),QString(),QDBusConnection::sessionBus(),this);
2 信號的綁定(注意:接收必須在DBus中註冊的對象中接收)
QObject::connect(myInterface,SIGNAL(checkIn(int)),this,SLOT(checkInSlot(int)));
注意點:
1 信號的發射端要想信號發射到DBus上去,在對象的構造函數中必須,註冊對象自己,必須使用this指針。例如:connection.registerobject(“/com/dbus/path”,this);
這樣這個類中的所有的信號都可以直接用emit發射到DBus總線上。
2 信號的接受端綁定信號是可以使用QTDBus的綁定也可以直接使用QObject的綁定。
當使用Qobject的綁定時,QObject::connect(dbusInterface,SIGNAL(testMessage),this,SLOT(testEvent);
創建接口時,接口的頭兩個參數必須爲空,例如:
dbusInterface =new dbus::test::interface(QString(),QString(),QDBusConnection::session(),this);
綁定的信號必須是已經導出的在interface文件有的。
當使用QDBus的綁定時,不論前兩個參數是否爲空,都可以正常的接受到信號
3 只有註冊到DBus上去對象才能接受打DBus上的信號,其他的對象要接受DBus上的信號必須通過這個註冊的對象將信號轉發出來。
QObject::connect(myInterface,SIGNAL(queryReply(int)),this,SIGNAL(queryResult(int)));