網上一搜,關於D-Bus和QT的資料很多,可是絕大多數都對傳遞自定義數據類型這個問題閉口不談。看來這個有必要寫個文章記錄一下。node
首先要說的是,我這裏再也不介紹D-Bus和QDbus的基礎知識,本文直擊要點。另外本文參考了KDE的一些文檔。函數
需求:使用標準的信號和槽,經過QDBus傳遞自定義的struct或者class數據類型。工具
首先,須要定義須要經過D-Bus傳遞的自定義數據類型,咱們這裏定義一個Message類型:
#include <QtDBus>
class Message
{
public:代理構造函數等略xml
friend QDBusArgument &operator<<(QDBusArgument &argument, const Message &message);接口
friend const QDBusArgument &operator>>(const QDBusArgument &argument, Message &message);文檔
static void registerMetaType();
private:
QString m_strMessage;
};
Q_DECLARE_METATYPE(Message)get
能夠看到有幾個比較特殊的地方:io
首先咱們重載了<<和>>兩個運算符,這是將自定義數據類型融合到QT的類型系統所必需的:
QDBusArgument &operator<<(QDBusArgument &argument, const Message& message)
{
入門argument.beginStructure();
argument << message.m_strMessage;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, Message &message)
{
argument.beginStructure();
argument >> message.m_strMessage;
argument.endStructure();
return argument;
}
其次,這個自定義數據類型須要註冊到QT和D-Bus的類型系統:
void Message::registerMetaType()
{qRegisterMetaType<Message>("Message");
qDBusRegisterMetaType<Message>();
}
有了這個數據類型,就能夠寫描述D-Bus接口的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="demo.Action">
<signal name="messageSent">
<arg name="message" type="a(i)" direction="out"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="Message"/>
</signal>
<method name="sendMessage">
<arg name="message" type="a(i)" direction="in"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="Message"/>
</method>
</interface>
</node>
這裏有兩個特殊點,一個是參數的數據類型,由於是咱們自定義的,不存在於D-Bus規範中,因此參數的type在這裏能夠亂寫。另外一個就是,既然是自定義的,就要說明這個自定義的數據類型究竟是啥(在這裏是Message)。
OK,有了上面這些囉嗦的準備工做,下面調用QT自帶的D-Bus工具,就能夠自動生成相關的接口和代理類了:
qdbusxml2cpp Chat.xml -i Message.h -a MessageAdaptor
qdbusxml2cpp Chat.xml -i Message.h -p MessageInterface
後續就是標準的調用QDBus過程了,本文再也不廢話,請參考其餘入門資料。大致上就是這樣:
接收:
connect(&m_MessageInterface, SIGNAL(messageSent(Message)), SLOT(onMessageSent(Message)));
發送:
Message message(…);
m_MessageInterface.sendMessage(message);