كيفية استخدام Qt-dbus تثبيت الارتباطات دون عرقلة الخيط الرئيسي
-
26-12-2019 - |
سؤال
هدفي هو إنشاء مكتبة باستخدام كيو تي هو 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]