문제

내 목표는 다음을 사용하여 라이브러리를 만드는 것입니다. Qt의 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;
    }
};

메인.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 라이브러리 헤더를 포함하려고 시도합니다. 포함경로 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