QtDbusパート2.純粋な心の輝かしい輝き

前の部分は悲観的な予測を残していましたが、すべてがはるかに、はるかに優れていることが判明しました。



ボーナスレベル分析
そこで、KOL93 harazhitelのおかげで、彼はQDbusAbstractAdaptorには親が必要であるという事実に注目しました。 それは私にとってニュースであることが判明しました、なぜなら 私は親がそうでないかもしれないという事実に非常に慣れています。 たぶん、これは他の誰かをそのような失態から救うでしょう。



さらに、私のパターンの無知、そのような特許「アダプター」があります。 QAbstractAdaptorは実際これです。 上記およびドックは、このクラスは軽量の例であるべきだと述べているので、本当に明確なアプローチは次のようになります。

Pongプロジェクト:
main.cpp
#include <QCoreApplication> #include <QDBusConnection> #include <QDBusError> #include <QDebug> #include "Pong.h" #include "../serviceNameAndProperty.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QDBusConnection connection = QDBusConnection::sessionBus(); Pong pong; if( ! connection.registerObject("/", &pong)){ fprintf(stderr, "%s\n", qPrintable("Can't register object")); exit(1); } qDebug()<<"Pong connected to D-bus"; if (!connection.registerService(SERVICE_NAME)) { fprintf(stderr, "%s\n", qPrintable(QDBusConnection::sessionBus().lastError().message())); exit(1); } qDebug()<<"Test service start"; return a.exec(); }
      
      



Pong.h
 #ifndef PONG_H #define PONG_H #include <QDBusAbstractAdaptor> #include <QDBusVariant> #include <QDBusArgument> #include <QDBusContext> #include "../serviceNameAndProperty.h" class Pong; class PongAdapter : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", BUFFER_NAME) Q_PROPERTY(QString IMAGE_DATA_SHARED_ID READ imageDataSharedId) public: explicit PongAdapter(Pong *parent); QString imageDataSharedId(); public slots: TestStructure structureField(); signals: void callingMe(QString, QString); private: Pong * m_parentPong; }; class Pong : public QObject, public QDBusContext { Q_OBJECT public: Pong() { m_pongAdapter = new PongAdapter(this); QObject::connect(this, SIGNAL(callingMe(QString,QString)), m_pongAdapter, SIGNAL(callingMe(QString, QString))); m_imageDataSharedId = "testImageBufferId"; } public: QString imageDataSharedId(); TestStructure& structureField(); signals: void callingMe(QString, QString); private: PongAdapter *m_pongAdapter; QString m_imageDataSharedId; TestStructure test; }; #endif // PONG_H>
      
      



Pong.cpp
 #include "Pong.h" #include <QDebug> #include <QDBusMetaType> #include <QDBusConnection> #include <QDBusMessage> PongAdapter::PongAdapter(Pong *parent) : QDBusAbstractAdaptor(parent) { m_parentPong = parent; qRegisterMetaType<TestStructure>("TestStructure"); qDBusRegisterMetaType<TestStructure>(); } QString PongAdapter::imageDataSharedId() { return m_parentPong->imageDataSharedId(); } TestStructure PongAdapter::structureField() { return m_parentPong->structureField(); } QString Pong::imageDataSharedId() { return m_imageDataSharedId; } TestStructure &Pong::structureField() { qDebug()<<"Me calld"<<QDBusConnection::sessionBus().baseService()<<message().service(); emit callingMe(QString("Panic"), QString("Super panic")); test.str = QString("ku"); test.id =2; return test; }
      
      



Pingプロジェクト:
main.cpp
 #include <stdio.h> #include <QObject> #include <QCoreApplication> #include <QDBusConnection> #include <QDBusConnectionInterface> #include <QDBusServiceWatcher> #include <QDebug> #include "Ping.h" #include "../serviceNameAndProperty.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Ping ping; if (!QDBusConnection::sessionBus().isConnected()) { fprintf(stderr, "Cannot connect to the D-Bus session bus.\n" "To start it, run:\n" "\teval `dbus-launch --auto-syntax`\n"); return 1; } qDebug()<<"Ping connected to D-bus"; QDBusConnectionInterface *iface = QDBusConnection::sessionBus().interface(); QDBusServiceWatcher watcher; watcher.setConnection(QDBusConnection::sessionBus());; watcher.addWatchedService(ping.m_aviableServiceName); // QObject::connect(&watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),&ping, SLOT(manageConnection(QString,QString,QString))); QObject::connect(&watcher, SIGNAL(serviceRegistered(QString)), &ping, SLOT(connectToService(QString))); QStringList registedServices = iface->registeredServiceNames(); if(registedServices.contains(ping.m_aviableServiceName)) ping.connectToService(ping.m_aviableServiceName); return a.exec();
      
      





}
Ping.h
 #ifndef PING_H #define PING_H #include <QObject> #include <QDBusAbstractInterface> #include <qdbusinterface.h> class Ping : public QObject { Q_OBJECT public: explicit Ping(QObject *parent = 0); public slots: void manageConnection(const QString &name, const QString &oldVAlue, const QString &newValue); void connectToService(const QString &name); void disconnect(const QString &name); void reacoOnMeCalling(QString message, QString message2); public: QString m_aviableServiceName; private: QDBusInterface *m_interface; QString m_interfaceName; static const QString _propertyName; }; #endif // PING_H
      
      





Ping.cpp
 #include "Ping.h" #include "../serviceNameAndProperty.h" #include <QDBusConnectionInterface> #include <QDebug> #include <QDBusMetaType> const QString Ping::_propertyName(QUIOTING(IMAGE_DATA_SHARED_ID)); Ping::Ping(QObject *parent) : QObject(parent) { m_interface = NULL; m_interfaceName = QString(BUFFER_NAME); m_aviableServiceName = QString(SERVICE_NAME); qRegisterMetaType<TestStructure>("TestStructure"); qDBusRegisterMetaType<TestStructure>(); } void Ping::manageConnection(const QString& name, const QString &oldVAlue, const QString &newValue) { Q_UNUSED(oldVAlue) if(name != m_aviableServiceName) return; if(newValue.isEmpty()) disconnect(name); else connectToService(name); } void Ping::connectToService(const QString &name) { if(name != m_aviableServiceName) return; qDebug()<<"Connceting"; m_interface = new QDBusInterface(name, "/", m_interfaceName, QDBusConnection::sessionBus(), this); QObject::connect(m_interface, SIGNAL(callingMe(QString, QString)), this, SLOT(reacoOnMeCalling(QString, QString))); if(!m_interface->isValid()){ qDebug()<<"Invalid interface"<<m_interface->lastError(); delete m_interface; m_interface = NULL; return; } qDebug()<<m_interface->interface(); QVariant var("sss"); var = m_interface->property("imageDataSharedId"); qDebug()<<var; QDBusReply<TestStructure> reply= m_interface->call("structureField"); if(reply.isValid()) { TestStructure testStructure = reply.value(); qDebug()<<testStructure.id<<testStructure.str; } } void Ping::disconnect(const QString &name) { if(name != m_aviableServiceName) return; if(name != m_interface->service()) return; delete m_interface; m_interface = NULL; qDebug()<<"Disconnect"; } void Ping::reacoOnMeCalling(QString message, QString message2) { qDebug()<<message<<message2; }
      
      





共有ファイルserviceNameAndProperty.h
 #pragma once #include<QMetaType> #include <QString> #include <QDBusArgument> #define SERVICE_NAME "ru.sonarh.dbus.pong" #define BUFFER_NAME "ru.buffer" #define IMAGE_DATA_SHARED_ID imageDataSharedId #define QUIOTING(text) #text struct TestStructure{ int id; QString str; }; Q_DECLARE_METATYPE(TestStructure) static QDBusArgument& operator <<(QDBusArgument &argument, const TestStructure & arg) { argument.beginStructure(); argument<<arg.id<<arg.str; argument.endStructure(); return argument; } static const QDBusArgument& operator >>(const QDBusArgument &argument, TestStructure & arg) { argument.beginStructure(); argument>>arg.id>>arg.str; argument.endStructure(); return argument; }
      
      





そしてまだ、それを使用する方法?
モジュールの使用方法のアイデアの整合性のために、過去を繰り返すことを許可します。 繰り返しの利点は学習の母です。

Pongクラスがあるので、D-Bus通信で使用できるようにします。 これに必要なもの:

  1. D-Busデーモンに接続します。 どこでも構いませんが、標準タイヤには既製の静的メソッドがあります。 この例では、この呼び出しはすぐに検証が行われます
     if (!QDBusConnection::sessionBus().isConnected()) {
          
          



  2. 利便性と確実性のために、DNSに似た名前をサービスに割り当てることができます。 Pongプロジェクトに対してこれを行います。
     if (!connection.registerService(SERVICE_NAME)) {
          
          



    重要! ピリオドという少なくとも1つの区切り文字が含まれている必要があります。
  3. 親がPongになるアダプターを作成します。 このアダプタは、外部から信号を受信し、反対方向とまったく同じように、親にリダイレクトします。 また、デザイナーの考えによれば、アダプターは実際にはアダプターであり、その助けを借りて既存のアプリケーションを拡張するのは非常に簡単であることを強調します。 以下に、プログラムからD-Busの世界への信号がどうやって発生するかを示します。
     QObject::connect(this, SIGNAL(callingMe(QString,QString)), m_pongAdapter, SIGNAL(callingMe(QString, QString)));
          
          



    重要! Q_ClASSINFOで指定されたアダプターインターフェイスの名前には、ピリオドが含まれている必要があります。
  4. ポンを登録しないでください。 次のようになります。
      if( ! connection.registerObject("/", &pong)){
          
          



    重要! このパスには少なくとも1つの区切り文字が含まれている必要があります- /
この話の興味深いひねりは、スロットをアクティブにしたメッセージのコンテキストを知りたい場合、 QDbusContextから実際のオブジェクト(Pong)を継承する必要がありますが、同時に、コンテキストメソッド、ala メッセージをアダプターにプルする必要があることですD-Busから抽象化し、テスト時に頭痛の種にならないようにします。 かなり奇妙なターンですが、これまでのところ私は不便に遭遇していません。



そして、すでにコンテキストについて話し始めているので、モジュール全体の核心に言及するしかありません。 そして、心は2室です。最初のカメラはQDbusMessageです。 参加者が交換するのと同じメッセージ。2番目のカメラはQDbusArgumentとQDbusReplyの形式での解釈です。 原則として、メッセージは手動で作成できます。 たとえば、dbusviwerでプロパティにアクセスするには、次のようにします。
 QDBusMessage message = QDBusMessage::createMethodCall(sig.mService, sig.mPath, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); QList<QVariant> arguments; arguments << sig.mInterface << sig.mName; message.setArguments(arguments); c.callWithCallback(message, this, SLOT(dumpMessage(QDBusMessage))); QDBusInterface iface(sig.mService, sig.mPath, sig.mInterface,c); if( !iface.isValid()) qDebug()<<(QDBusError(iface.lastError()).message()); else qDebug()<<iface.property(sig.mName.toLatin1().data());
      
      





ただし、QDbusArgumentメッセージの形成を委任する方がはるかに簡単です。 このために必要なものは2つだけです。型が基本的なQt標準に適合しない場合は>> >>演算子を実装します
 struct TestStructure{ int id; QString str; }; Q_DECLARE_METATYPE(TestStructure) static QDBusArgument& operator <<(QDBusArgument &argument, const TestStructure & arg) { argument.beginStructure(); argument<<arg.id<<arg.str; argument.endStructure(); return argument; }
      
      





そして、最初に使用する前に、qDBusRegisterMetaTypeを呼び出します。 そしてその後、困難は終わります: QDbusInterfaceの助けを借りて、必要なメソッドを呼び出します。それがvoidメソッドではなく、戻り値が私たちにとって重要で必要な場合は、テンプレートクラスQDbusReplyを使用します。

それだけです、本当にすべてです。 モジュールについての知識が完成しました。正面には、使用すべきフィールドのみがあります。



All Articles