この記事の概要
Qt を用いたD-Bus通信(QtDBus) - その2の続きです。
送受信処理の実装
前回に引き続き、実装を行っていきます。
同期・非同期通信による送受信を行う、サンプルアプリとして github に登録しておきました。
github: QtDBusSample
※あまり行儀よいソースではないと思います。本題のDBus通信以外も含めて問題点ご指摘いただければ。
ビルド&実行方法や、アプリの動作などについては、この記事の末尾に記載しておきます。
3. QtDBus を用いたコーディング
通信を行うためには、同期・非同期、及び送受信側で一定の処理をそれぞれで行う必要があります。
なお、先述の通りサービス名の登録は任意で、未登録だと番号での名前が動的に割り当てられます。
ただ、サンプルソースをシンプルにするためにも、サービス名を固定化して送受信を行っています。
共通処理部 : setupDBus()
- Session Bus か System Bus を指定して DBus に接続
- ここでは接続可否の確認だけですが、送受信相手との接続の際にも使います。
- Service 名の登録
- Object 名の登録
- Adaptor インスタンスの作成
QDBusConnection sessionBus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, 識別名);
sessionBus.registerService(サービス名);
sessionBus.registerObject(オブジェクト名, this);
new IfnameAdaptor(this); //インスタンスの保持は不要(QObject派生のため破棄も不要)
同期送信部 : sendSyncMessage()
不特定多数に送信する通信のため、送信時に誰が(Object)どの送信(Signal)を行ったのかを明示するだけです。
QDBusMessage stream = QDBusMessage::createSignal(
オブジェクト名,
インターフェース名,
シグナル名);
stream << [signal 指定で作成した関数の引数に合わせたデータ];
sessionBus.send(stream);
同期受信部 : recvSyncMessage(const QByteArray &data) / connectSyncMessage()
受信時の処理を行う SLOT 関数(Qt固有)を用意し、
期待した送信主(Object)のどの送信(Signal)があった場合に、その SLOT が駆動するように登録します。
この登録には、Qt 固有の SIGNAL/SLOT を用います。
private slots:
void DBusReceiver::recvSyncMessage(const QByteArray &data)
{
//受信処理
}
sessionBus.connect(
送信主のサービス名,
送信主のオブジェクト名,
インターフェース名,
送信主の Signal 関数名,
this,
SLOT(Signalの引数に合わせた、Qt固有のSLOT関数));
非同期送信部 : createInterface() / sendAsyncMessage()
前回 XML から作成した Interface クラスのインスタンスを、送り先の Service 名、Object 名を指定しつつ作成し、
送信の際には、同じく XML で作成した非同期受信関数(Method)を経由して、引数として相手に送信します。
iface = new com::servicename::ifname(
送信先サービス名
送信先オブジェクト名,
sessionBus,
this);
iface->asyncInvoke(文字列);
非同期受信部() : asyncInvoke(const QByteArray &data)
前回 XML から作成した Adaptor クラスのインスタンスを作成して導通しておけば、Qt固有の SIGNAL/SLOT の SLOT 部を用意するだけです。
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 |