كيفية استخدام Qt-dbus تثبيت الارتباطات دون عرقلة الخيط الرئيسي

StackOverflow https://stackoverflow.com//questions/24058519

سؤال

هدفي هو إنشاء مكتبة باستخدام كيو تي هو dbus تثبيت الارتباطات.

حاولت إنشاء تطبيق Qt دون إطلاق QEventLoop (تقدمها QCoreApplication الطبقة) في الموضوع الرئيسي.

هنا هو أضيق الحدود تطبيق العينة ، تعمل بشكل جيد باستخدام QT-4.6.2 النسخة ولكن حظر على التأمل باستخدام QT-4.8 أو أعلى.

DBusHandler.hpp

#pragma once
#include <iostream>
#include <QtCore/QThread>
#include <QtCore/QtCore>
#include <QtDBus/QDBusInterface>

class DBusHandler : public QThread
{
    Q_OBJECT;

private:     
    void run(void)
    {
        QDBusConnection connection = QDBusConnection::sessionBus();

        connection.registerService("my.qdbus.example");
        connection.registerObject("/", this, QDBusConnection::ExportAllSlots);
        exec();
    }

public:
    DBusHandler(void) {}
    virtual ~DBusHandler(void) {}

    void stop(void)
    {
        QDBusConnection connection = QDBusConnection::sessionBus();

        connection.unregisterObject("/");
        connection.unregisterService("my.qdbus.example");
        connection.disconnectFromBus(connection.name());
        QThread::quit();
    }

public slots:
    void remoteCall(QByteArray message)
    {
        std::cout << "Message size: " << message.size() << std::endl;
    }
};

main.cpp

#include "DBusHandler.hpp"

int main(int ac, char **av)
{
    QCoreApplication app(ac, av);
    DBusHandler handler;

    handler.moveToThread(&handler);

    handler.start();
    while (not handler.isRunning());

    // app.exec();
    sleep(10); // Gives time to call using the command line: "qdbus my.qdbus.example / local.DBusHandler.remoteCall a_message"

    handler.stop();
    while (handler.isRunning());
}

كما يمكنك أن ترى في main.cpp الملف ، app.exec() وعلق بها ، ولكن يجعل التطبيق يعمل بشكل جيد على QT-4.8 أو إصدارات أعلى (5.3.0).

سؤالي هو التالي:هل من الممكن استخدام Qt هو dbus تثبيت ربط الاتصال app.exec() في الصفحات الأخرى من واحدة رئيسية ، على Qt-4.8 5.3 ?

هل كانت مفيدة؟

المحلول

الخلفية:هناك فئة خاصة تسمى QDBusConnectionPrivate الذي يرث من QObject و يتعامل مع جميع الشبكات.للأسف, إذا نظرتم qdbusconnection.cpp:1116 سترى أن Qt الثابت رموز moveToThread إلى QCoreApplication::instance().

ربما يجب عليك تقديم طلب تحسين تسمح للمستخدم لإنشاء QDBusConnection يستخدم المستخدم تحديد الموضوع أو الحدث حلقة. راجع تحديث أدناه.

في هذه الأثناء, إذا كنت مرتاحا القيام ببعض الأمور الخطيرة, يمكنك الإختراق في نفسك من خلال خلق الخاصة بك QDbusConnection فرعية (دعوت لي SpecializedDBusConnection) أن يأخذ QThread كما الوسيطة الثالثة من حيث تريد QDbusConnectionPrivate سبيل المثال يمكن نقلها إلى.ثم استخدام تلك الفئة لإنشاء اتصال بدلا من الافتراضي QDbusConnection::sessionBus().

لأن هذا هو استخدام بعض فصول خاصة ، يتطلب إدراج بعض الملفات رأس (لاحظ في الكود أدناه) والتي بدورها سوف محاولة تشمل مختلف dbus تثبيت مكتبة رؤوس والتي سوف تتطلب التعديل INCLUDEPATH المشروع ليشمل dbus تثبيت مكتبة تشمل المسار.

لقد تم التحقق من هذا يعمل على Qt 5.3.0 و Qt 4.8.6.

تحديث: في Qt 5.6, QtDBus كان بتعميل الترميز إلى استخدام المواضيع ل واردة/المنتهية ولايته رسالة التجهيز ؛ لا مزيد من حجب الخيط الرئيسي!

DBusHandler.hpp

#pragma once
#include <iostream>
#include <QtCore/QThread>
#include <QtCore/QtCore>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusConnectionInterface>

#include "/path/to/Qt5.3.0/5.3/Src/qtbase/src/dbus/qdbusconnection_p.h"

class SpecializedDBusConnection : public QDBusConnection {
    const char *ownName;
public:
    inline SpecializedDBusConnection(BusType type, const char *name, QThread *thread)
        : QDBusConnection(connectToBus(type, QString::fromLatin1(name))), ownName(name)
    {
        if (QDBusConnectionPrivate::d(*this)) {
            QDBusConnectionPrivate::d(*this)->moveToThread(thread);
        }
    }

    inline ~SpecializedDBusConnection()
    { disconnectFromBus(QString::fromLatin1(ownName)); }
};

class DBusHandler : public QThread
{
    Q_OBJECT;

private:     
    void run(void)
    {
        QDBusConnection connection = SpecializedDBusConnection(QDBusConnection::SessionBus, "qt_default_session_bus", this);

        connection.registerService("my.qdbus.example");
        connection.registerObject("/", this, QDBusConnection::ExportAllSlots);

        exec();
    }
[snip]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top