c++ - QDbus 信号不工作(暂停交付)
问题描述
对于我的项目,我需要使用带信号的 DBus。为此,我尝试将D-Bus Remote Controlled Car Example中可用的示例程序转换为在 linux ARM A7 处理器(使用 Qt 5.12.8)上运行。我已经意识到以下步骤:
- 用文本输出替换所有 HMI 引用并简化程序。
- 迁移项目以在 qmake 的地方使用 CMake(最终项目中使用 Cmake > 3.0)
汽车文件夹中的 CMakeLists.txt:
set(QT_LIBS Qt5::Core Qt5::DBus)
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/car_adaptor.h ${CMAKE_CURRENT_SOURCE_DIR}/car_adaptor.cpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
COMMENT "Generate adaptors files for Dbus service"
COMMAND /opt/dip/2.7-warrior+snapshot/sysroots/x86_64-dipsdk-linux/usr/bin/qdbusxml2cpp -a car_adaptor.h: ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
COMMAND /opt/dip/2.7-warrior+snapshot/sysroots/x86_64-dipsdk-linux/usr/bin/qdbusxml2cpp -i car_adaptor.h -a :car_adaptor.cpp ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_executable (car
main.cpp
car.cpp
car_adaptor.cpp
)
set_target_properties(car PROPERTIES AUTOMOC TRUE)
target_link_libraries(car ${QT_LIBS})
控制器文件夹中的 CMakeLists.txt:
set(QT_LIBS Qt5::Core Qt5::DBus)
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/car_interface.h ${CMAKE_CURRENT_SOURCE_DIR}/car_interface.cpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
COMMENT "Generate interface files for Dbus service"
COMMAND /opt/dip/2.7-warrior+snapshot/sysroots/x86_64-dipsdk-linux/usr/bin/qdbusxml2cpp -p car_interface.h: ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
COMMAND /opt/dip/2.7-warrior+snapshot/sysroots/x86_64-dipsdk-linux/usr/bin/qdbusxml2cpp -i car_interface.h -p :car_interface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/car.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_executable (controller
main.cpp
controller.cpp
car_interface.cpp
)
set_target_properties(controller PROPERTIES AUTOMOC TRUE)
target_link_libraries(controller ${QT_LIBS})
问题描述
我的问题如下:通过这些更改,Dbus 信号似乎由汽车应用程序发出,但控制器应用程序没有接收到。我试图了解 DBus 调试模式 ( QDBUS_DEBUG=1 ) 问题的根源,但不明白为什么所有信号都有以下返回:QDBusConnectionPrivate(0x75d006d0) 交付被暂停 我可能错过了一件事,但我看不到什么。
测试输出:
export QDBUS_DEBUG=1
eval `dbus-launch --auto-syntax`
root@rzn1-embd:/tmp# ./car &
[1] 1391
root@rzn1-embd:/tmp# QDBusConnectionPrivate(0x75d006d0) : connected successfully
QDBusConnectionPrivate(0x75d006d0) got message (signal): QDBusMessage(type=Signal, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="NameAcquired", signature="s", contents=(":1.0") )
QDBusConnectionPrivate(0x75d006d0) sending message: QDBusMessage(type=MethodCall, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="RequestName", signature="", contents=("org.example.CarExample", 4) )
QDBusConnectionPrivate(0x75d006d0) delivery is suspended
QDBusConnectionPrivate(0x75d006d0) got message (signal): QDBusMessage(type=Signal, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="NameAcquired", signature="s", contents=("org.example.CarExample") )
QDBusConnectionPrivate(0x75d006d0) delivery is suspended
QDBusConnectionPrivate(0x75d006d0) got message reply: QDBusMessage(type=MethodReturn, service="org.freedesktop.DBus", signature="u", contents=(1) )
QDBusConnectionPrivate(0x75d006d0) dequeueing message QDBusMessage(type=Signal, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="NameAcquired", signature="s", contents=(":1.0") )
QDBusConnectionPrivate(0x75d006d0) dequeueing message QDBusMessage(type=Signal, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="NameAcquired", signature="s", contents=("org.example.CarExample") )
root@rzn1-embd:/tmp# ./controller
QDBusConnectionPrivate(0x75d006d0) : connected successfully
QDBusConnectionPrivate(0x75d006d0) got message (signal): QDBusMessage(type=Signal, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="NameAcquired", signature="s", contents=(":1.1") )
QDBusConnectionPrivate(0x75d006d0) delivery is suspended
QDBusConnectionPrivate(0x75d006d0) Adding rule: "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.example.CarExample'"
QDBusConnectionPrivate(0x75d006d0) sending message: QDBusMessage(type=MethodCall, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="GetNameOwner", signature="", contents=("org.example.CarExample") )
QDBusConnectionPrivate(0x75d006d0) got message reply: QDBusMessage(type=MethodReturn, service="org.freedesktop.DBus", signature="s", contents=(":1.0") )
QDBusConnectionPrivate(0x75d006d0) Adding rule: "type='signal',sender='org.example.CarExample',path='/Car',interface='org.example.Examples.CarInterface',member='crashed'"
QDBusConnectionPrivate(0x75d006d0) sending message: QDBusMessage(type=MethodCall, service="org.freedesktop.DBus", path="/org/freedesktop/DBus", interface="org.freedesktop.DBus", member="GetNameOwner", signature="", contents=("org.example.CarExample") )
QDBusConnectionPrivate(0x75d006d0) got message reply: QDBusMessage(type=MethodReturn, service="org.freedesktop.DBus", signature="s", contents=(":1.0") )
QDBusConnectionPrivate(0x75d006d0) Watching service "org.example.CarExample" for owner changes (current owner: ":1.0" )
Menu:
- Q: quitter
- 1: Accelerate
- 2: Decelerate
1
QDBusConnectionPrivate(0x75d006d0) sending message: QDBusMessage(type=MethodCall, service="org.example.CarExample", path="/Car", interface="org.example.Examples.CarInterface", member="accelerate", signature="", contents=() )
QDBusConnectionPrivate(0x75d006d0) got message (signal): QDBusMessage(type=MethodCall, service=":1.1", path="/Car", interface="org.example.Examples.CarInterface", member="accelerate", signature="", contents=() )
Speed: 1
QDBusConnectionPrivate(0x75d006d0) Automatically sending reply: ()
QDBusConnectionPrivate(0x75d006d0) sending message (no reply): QDBusMessage(type=MethodReturn, service="", signature="", contents=() )
QDBusConnectionPrivate(0x75d006d0) got message reply: QDBusMessage(type=MethodReturn, service=":1.0", signature="", contents=() )
QThread(ptr=0x76f0d370, name=QDBusConnectionManager) emitting signal at "/Car"
QDBusConnectionPrivate(0x75d006d0) got message (signal): QDBusMessage(type=Signal, service=":1.0", path="/Car", interface="org.example.Examples.CarInterface", member="crashed", signature="", contents=() )
QDBusConnectionPrivate(0x75d006d0) delivery is suspended
修改后的源文件:
汽车.h
#ifndef CAR_H
#define CAR_H
#include <QObject>
class Car : public QObject
{
Q_OBJECT
public:
Car();
public Q_SLOTS:
void accelerate();
void decelerate();
Q_SIGNALS:
void crashed();
private:
int speed; // delta movement along the body axis
};
#endif // CAR_H
汽车.cpp
#include "car.h"
#include <QDebug>
Car::Car() : speed(0) {}
void Car::accelerate() {
if (speed < 10)
++speed;
qInfo() << "Speed: " << speed << endl;
if (speed > 0)
emit crashed();
}
void Car::decelerate() {
if (speed > -10)
--speed;
qInfo() << "Speed: " << speed << endl;
}
汽车/main.cpp
#include "car.h"
#include "car_adaptor.h"
#include <QCoreApplication>
#include <QtDBus/QDBusConnection>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
Car *car = new Car();
new CarInterfaceAdaptor(car);
QDBusConnection connection = QDBusConnection::sessionBus();
connection.registerObject("/Car", car);
connection.registerService("org.example.CarExample");
return app.exec();
}
控制器/main.cpp
#include <QtDBus>
#include <QCoreApplication>
#include "controller.h"
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
Controller controller;
controller.start();
return app.exec();
}
控制器.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include "car_interface.h"
#include <QObject>
class Controller : public QObject
{
Q_OBJECT
public:
Controller(QObject *parent = 0);
void start();
private slots:
void on_accelerate_clicked();
void on_decelerate_clicked();
void onCrashed();
private:
org::example::Examples::CarInterface *car;
void displayMenu();
};
#endif
控制器.cpp
#include "controller.h"
#include "car_interface.h"
#include <QDebug>
Controller::Controller(QObject *parent) : QObject(parent) {
car = new org::example::Examples::CarInterface(
"org.example.CarExample", "/Car", QDBusConnection::sessionBus(), this);
connect(car, SIGNAL(crashed()), this, SLOT(onCrashed()));
}
void Controller::start() {
char key = 0;
displayMenu();
while (key != 'Q') {
key = getchar();
switch (key) {
case '1': on_accelerate_clicked(); break;
case '2': on_decelerate_clicked(); break;
case 'Q': exit(1); break;
}
}
}
void Controller::on_accelerate_clicked() { car->accelerate(); }
void Controller::on_decelerate_clicked() { car->decelerate(); }
void Controller::onCrashed() { qInfo() << "Controller: crashed"; }
void Controller::displayMenu() {
qInfo() << "\r\nMenu:";
qInfo() << "\t- Q: quitter";
qInfo() << "\t- 1: Accelerate";
qInfo() << "\t- 2: Decelerate";
}
解决方案
在控制器的main()
函数中,执行永远不会过去controller.start()
,因为此方法包含while
不断轮询键盘输入的循环,如果按下“Q”,它会立即退出。
因此,您永远无法到达app.exec()
运行 Qt 事件循环的位置,并且仅在事件循环内接收和处理 DBus 信号。
您应该切换以处理基于键盘按下事件的事件。或者,如果你想保持while
循环,你应该修改它,至少QCoreApplication::processEvents()
(参见它的文档)经常被调用。
推荐阅读
- keyboard - 如何仅针对特定键盘布局(karabiner)启用规则?
- java - QSELL 中的 IBM JAVA_HOME 设置不起作用
- python - 在 Python 中使用网格搜索创建维度为 n * 3 的矩阵
- java - 如何从命令行将 JSP 转换为 Servlet?
- javascript - 为什么我的 javascript 函数被打印为未定义?
- amazon-web-services - iot.createKeysAndCertificate 没有按照 AWS 的建议正常工作。如何解决?
- php - PHP:在排序多维对象数组时需要帮助(数组需要按[Zone] => stdClass Object([Description] => Price B Box Circle)排序
- node.js - 开发 NodeJS docker 容器观察文件系统更改并在崩溃时重新启动的最佳方式是什么?
- python - Python 3.6 - 创建下拉菜单以选择文件夹中的文件
- python - 如何在 Visual Studio 中为 Python 激活 VENV?