LoginSignup
4
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-11-15

この記事の概要

Qt を用いたD-Bus通信(QtDBus) - その2の続きです。

送受信処理の実装

前回に引き続き、実装を行っていきます。

同期・非同期通信による送受信を行う、サンプルアプリとして github に登録しておきました。
github: QtDBusSample

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

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

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

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

共通処理部 : setupDBus()

  • Session Bus か System Bus を指定して DBus に接続
    • ここでは接続可否の確認だけですが、送受信相手との接続の際にも使います。
  • Service 名の登録
  • Object 名の登録
  • Adaptor インスタンスの作成
dbus_sender.cpp,dbus_receiver.cpp
QDBusConnection sessionBus = QDBusConnection::connectToBus(QDBusConnection::SessionBus, 識別名);

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

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

同期送信部 : sendSyncMessage()

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

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 を用います。

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)を経由して、引数として相手に送信します。

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

iface->asyncInvoke(文字列);

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

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

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
4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6