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

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

# 実作業
それでは、実際に行う作業をおって説明していきます。
ここでは、同期／非同期通信両方ができる最小限の送受信アプリを作成していきます。

## 1. XML で Interface 名や Signal ／ Method の関数(引数の数と種別、戻り値も含む)の定義

まず、前述の「開発の流れ」の最初の項目です。

初っ端から目的の実コード以外のファイルを作成する必要があり、この時点でかなり戸惑いました。
また、本家以外に説明しているサイトもなかなか見つからなかったため、ここで概要を説明します。
細かい設定値の定義については、本家、及び Qt のドキュメントを参照してください。

* [D-Bus Specification](http://dbus.freedesktop.org/doc/dbus-specification.html)
* [D-Bus API Design Guidelines](http://dbus.freedesktop.org/doc/dbus-api-design.html)

下記は、Interface 名、同期通信、非同期通信用の定義をそれぞれ１つずつ定義した XML ファイルです。

```xml:com.servicename.ifname.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.servicename.ifname">

    <!-- void syncSend(QByteArray data) -->
    <signal name="syncSend">
       <arg name="data" type = "ay" direction="out"/>
    </signal>

    <!-- QString asyncInvoke(QByteArray data) -->
    <method name="asyncInvoke">
       <arg name="data" type = "ay" direction="in"/>
       <arg type = "s" direction="out"/>
    </method>

  </interface>
</node>
```

この XML では、以下の定義を行っています。

* interface 名を`com.servicename.ifname` として定義
* interface に属する、同期通信の送信関数(Signal)、`void syncSend(QByteArray data)` の定義
* interface に属する、非同期通信の受信関数(Method)、`QString asyncInvoke(QByteArray data)` の定義

(同期通信は戻り値を指定できません。対して非同期通信では、戻り値を介して応答処理を組むことができます)

### interface 名の定義

```
<interface name="com.servicename.ifname">
			:
</interface>
```

[Qt を用いたD-Bus通信(QtDBus) - その１](http://qiita.com/Corgeek/items/8f5f9918e9d708dc5c32) の用語の説明で出てきた、interface 部の名称を定義しています。


### 同期通信の送信関数(signal)

```
    <signal name="syncSend">
       <arg name="data" type = "ay" direction="out"/>
    </signal>
```

* 関数の定義 : `<signal name="syncSend">` 同期通信用の関数名の指定になります。
* 引数の定義 : `<arg name="data" type = "ay" direction="out"/>`
 * name="data" : 変数名の指定
 * type = "ay" : 変数の型名の指定。"ay" は QByteArray を指しています。<br>その他、"i" は int 型、 "s" は QString 型など、組込み型、及び Qt が提供している型に対応しています。
 * direction="out" : 引数により送るため、"out"になります。

引数の定義は、羅列することで変数の数を増やせます。
例えば、以下のように書けば `void syncSend(int value, QByteArray data, QString text)` を定義することができます。

```
    <signal name="syncSend">
        <arg name="value" type = "i" direction="out"/>
        <arg name="data" type = "ay" direction="out"/>
        <arg name="text" type = "s" direction="out"/>
    </signal>
```

### 非同期通信の受信関数(method)

```
    <method name="asyncInvoke">
       <arg name="data" type = "ay" direction="in"/>
       <arg type = "s" direction="out"/>
    </method>
```

* 関数名の定義 : `<method name="asyncInvoke">` で非同期通信用の関数名の指定になります。
* 引数の定義 : `<arg name="data" type = "ay" direction="in"/>`
 * name="data" : 第一引数の変数名を "data" としています。
 * type = "ay" : data の型を QByteArray に指定しています。
 * direction = "in" : 引数により受信するため "in" になります。
* 戻り値の定義 : `<arg type = "s" direction="out"/>`
 * 戻り値のため名前の定義はできません。
 * type = "s" : 戻り値の型を QString 型に指定しています。
 * direction = "out" : 戻り値による受信からの応答、つまり出力"out"になります。<br>
(※戻り値も QDBusPendingReply を用いて複数子定義できるようですが未確認)

## 2. 1. で作成した XML ファイルを qdbusxml2cpp に食わせ、Interface/Adaptor部のソース＆ヘッダーファイルを自動生成

次に、Qt が提供しているツールを使い、作成した XML ファイルから ソース＆ヘッダーファイルを作成します。

環境にない場合、ubuntu 14.04 だと、以下のコマンドでインストールできます。

`$ sudo apt-get install qtbase5-dev-tools`

なお、自動生成したものはそのまま使えますが、雛形を自動生成する、という立ち位置で提供しているようで、
Qt 公式ドキュメントでも詳細は書かれておらず、必要に応じて修正するスタンスで利用したほうが良さそうです。

[Qt 公式 : Qt D-Bus XML compiler (qdbusxml2cpp)](http://doc.qt.io/qt-5/qdbusxml2cpp.html)


自動生成するファイルは、送受信の実装(Adaptor)部と結合(Interface)部のソース＆ヘッダーになります。
変換のコマンドは、上記で作成した XML ファイルを指定し、出力する Adaptor と Interface のファイル名を指定するだけです。

`qdbusxml2cpp xmlファイル名 -p Interfaceファイル名 -a Adaptorファイル名`

具体的には、上記 XML ファイルから生成する場合、以下のコマンドになります。

`$ qdbusxml2cpp com.servicename.ifname.xml -p sample_interface -a sample_adaptor`

このコマンドで、以下のファイルが生成されます。

* sample_interface.cpp
* sample_interface.h
* sample_adaptor.cpp
* sample_adaptor.h

ここまで来ると、あとは Qt の構文に沿ってコーディングしていくだけです。

区切りがいいので、続きは[その３](http://qiita.com/Corgeek/items/dee1a0d3a9a574d0938f)として投稿します。