Qt を用いたD-Bus通信(QtDBus) - その３

# この記事の概要
[Qt を用いたD-Bus通信(QtDBus) - その２](http://qiita.com/Corgeek/items/0693f48f0dcd454979fa)の続きです。

# 送受信処理の実装
前回に引き続き、実装を行っていきます。

同期・非同期通信による送受信を行う、サンプルアプリとして github に登録しておきました。
[github: QtDBusSample](https://github.com/Corgeek/QtDBusSample)

※あまり行儀よいソースではないと思います。本題のDBus通信以外も含めて問題点ご指摘いただければ。

ビルド＆実行方法や、アプリの動作などについては、この記事の末尾に記載しておきます。

## 3. QtDBus を用いたコーディング

通信を行うためには、同期・非同期、及び送受信側で一定の処理をそれぞれで行う必要があります。
なお、先述の通りサービス名の登録は任意で、未登録だと番号での名前が動的に割り当てられます。
ただ、サンプルソースをシンプルにするためにも、サービス名を固定化して送受信を行っています。

### 共通処理部 : setupDBus()

* Session Bus か System Bus を指定して DBus に接続
 * ここでは接続可否の確認だけですが、送受信相手との接続の際にも使います。
* Service 名の登録
* Object 名の登録
* Adaptor インスタンスの作成

```cpp:dbus_sender.cpp,dbus_receiver.cpp
QDBusConnection	sessionBus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, 識別名);

sessionBus.registerService(サービス名);
sessionBus.registerObject(オブジェクト名, this);

new IfnameAdaptor(this);				//インスタンスの保持は不要(QObject派生のため破棄も不要)
```

### 同期送信部 : sendSyncMessage()

不特定多数に送信する通信のため、送信時に誰が(Object)どの送信(Signal)を行ったのかを明示するだけです。

```cpp:dbus_sender.cpp
QDBusMessage stream = QDBusMessage::createSignal(
				オブジェクト名,
				インターフェース名,
				シグナル名);

stream << [signal 指定で作成した関数の引数に合わせたデータ];

sessionBus.send(stream);
```

### 同期受信部 : recvSyncMessage(const QByteArray &data) / connectSyncMessage()

受信時の処理を行う SLOT 関数(Qt固有)を用意し、
期待した送信主(Object)のどの送信(Signal)があった場合に、その SLOT が駆動するように登録します。
この登録には、Qt 固有の SIGNAL/SLOT を用います。

```cpp:dbus_receiver.cpp
private slots:
void DBusReceiver::recvSyncMessage(const QByteArray &data)
{
		//受信処理
}

sessionBus.connect(
				送信主のサービス名,
				送信主のオブジェクト名,
				インターフェース名,
				送信主の Signal 関数名,
				this,
				SLOT(Signalの引数に合わせた、Qt固有のSLOT関数));

```

### 非同期送信部 : createInterface() / sendAsyncMessage()

前回 XML から作成した Interface クラスのインスタンスを、送り先の Service 名、Object 名を指定しつつ作成し、
送信の際には、同じく XML で作成した非同期受信関数(Method)を経由して、引数として相手に送信します。

```cpp:dbus_sender.cpp
iface = new com::servicename::ifname(
				送信先サービス名
				送信先オブジェクト名,
				sessionBus,
				this);

iface->asyncInvoke(文字列);
```

### 非同期受信部() : asyncInvoke(const QByteArray &data)

前回 XML から作成した Adaptor クラスのインスタンスを作成して導通しておけば、Qt固有の SIGNAL/SLOT の SLOT 部を用意するだけです。

```cpp:dbus_recevier.cpp
private slots:
QString DBusReceiver::asyncInvoke(const QByteArray &data)
{
		//受信処理
		return 文字列;
}
```
# おわりに

D-Bus については、ツールを使った通信の傍受や送受信など、ユーザー視点での情報はあるものの、
開発者視点での D-Bus を取り扱う記事が見当たらず、今回投稿に至りました。

ただ、今回扱った D-Bus は、アプリレベルである Session Bus の D-Bus であり、
もう一方の、デバイスの検知や設定変更通知など、システム全体に及ぶ System Bus を扱う場合は、まだ不足している分があります。
こちらについては、自分の中で整理が付き次第、改めて投稿したいと思います。

D-Bus は、機能や用途を考えると、非常にポテンシャルが高く、Linux における存在感も日に日に増しています。
今後の発展や普及にも期待できるため(個人的に、勝手に次期 MS 製 OS に搭載を期待)、この辺の開拓が進められたらと思います。


なお、今回 github、qiita (というか blog 等も含め)ともに初めての利用で、イロイロお試し運用中です。
諸々見難いところ、わかりにくいところなどあるかも知れませんが、生温かく見守っていただければと思います。

## サンプルアプリについて

ビルド＆実行は以下で行えます(Qt5で確認)。

```
$ cd QtDBusSample
$ qmake
$ make
$ ./QtDBusSample
```

使い方は、DBusSender 側の QLineEdit に文字を入力、Enter キーで DBusReceiver に送信します。
チェックボックスのチェックありなしで、非同期／同期通信に切り替え、
受信側の DBusReceiver は、受け取った QByteArray の手前に 同期なら sync: を、非同期なら async: を付与して setText() しています。
また、非同期通信は戻り値を設定しており、DBusReceiver からの戻り値を DBusSender の Window タイトルに戻り値を表示しています。

それぞれ、サービス名などは以下になります。

| 項目 | DBusSender | DBusReceiver |
|:---:|:-----------:|:------------:|
| Service | com.servicename.sender | com.servicename.receiver |
| Object | com/servicename/sender | com/servicename/receiver |
| Interface | com.servicename.ifname | com.servicename.ifname |
| Signal | syncSend | syncSend(未定義) |
| Method | asyncInvoke(未定義) | asyncInvoke |