系统信息:
- QT5.10
- Ubuntu 16.04
使用 QtDBus,并使用以下 XML,我生成了 xyz_interface.hpp
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.blah.XYZ">
<signal name="Event">
<arg name="event_json" type="s" direction="out"/>
</signal>
<method name="AuthenticateUser">
<arg name="auth_req_json" type="s" direction="in"/>
<arg name="result" type="s" direction="out"/>
</method>
</interface>
</node>
创建接口后,连接接口的信号;
com::blah::Xyz interface = new com::blah::Xyz("com.blah.XYZ", "/com/blah/XYZ", QDBusConnection::systemBus(), this);
connect(interface , &com::blah::Xyz::Event, this, &SomeClass::HandleEvents)
当通过命令行使用dbus-send从 Xyz 发送信号时,我无法触发函数SomeClass::HandleEvents内的断点;
dbus-send --system --type=signal /com/blah/Xyz com.blah.XYZ.Event string:"hello"
使用dbus-monitor --system,我可以看到信号正在正确发出。
然后,在单元测试中,我创建了一个测试信号:
QDBusMessage xyz_signal = QDBusMessage::createSignal(
"/com/blah/XYZ", "com.blah.XYZ", "Event");
xyz_signal << "hello";
ASSERT_TRUE(connection.send(xyz_signal ));
那也未能触发断点。
在寻找解决方案数小时后,我放弃并创建了一些假的 python dbus 服务,这些服务在命令上发出事件信号(替换为 dbus-send),瞧……触发了断点并捕获了信号!(没有对 QT dbus 代码进行一次更改)
我能够接收从 python 代码发出的信号这一事实让我认为我的dbus-send --system --type=signal格式错误,但似乎无法修复它。
这是python代码;
import gobject
import dbus
import dbus.service
import dbus.mainloop.glib
class XyzService(dbus.service.Object):
@dbus.service.method("com.blah.Xyz",
in_signature='s', out_signature='s')
def AuthenticateUser(self, auth_req_json):
print (str("hello_message"))
return '''
{
"AuthenticationResponce" : "SUCCESS"
}
'''
@dbus.service.method("com.blah.Xyz",
in_signature='s')
def EmitEvent(self, str):
self.Event(str)
@dbus.service.signal('com.blah.Xyz', signature='s')
def Event(self, event_json):
# The signal is emitted when this method exits
# You can have code here if you wish
pass
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
system_bus = dbus.SystemBus()
name = dbus.service.BusName("com.blah.Xyz", system_bus)
object = XyzService(system_bus, '/com/blah/Xyz')
mainloop = gobject.MainLoop()
print "Running example service."
mainloop.run()
更新
我刚刚发现,如果我为路径和名称创建空字符串的接口,那么我能够接收命令行dbus-send 发送的信号
com::blah::Xyz interface = new com::blah::Xyz("", "", QDBusConnection::systemBus(), this);
上面的单元测试也通过了。
但现在我无法调用AuthenticateUser方法!这很令人困惑
更新 2
我能够通过此处找到的 QT 提供的 RemoteControlledCar dbus 示例重现该问题;https://code.qt.io/cgit/qt/qtbase.git/tree/examples/dbus/remotecontrolledcar?h=5.10
在controller.cpp 的构造函数中,我添加了以下内容;
Controller::Controller(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
car = new org::example::Examples::CarInterface("org.example.CarExample", "/Car",
QDBusConnection::sessionBus(), this);
// added signal listener
connect(car, &org::example::Examples::CarInterface::crashed,this,[](){qDebug("hello signal");});
startTimer(1000);
}
使用 dbus-send 触发信号时,不会打印消息 hello 信号。但是当我将服务路径和名称更改为空字符串时,我成功接收到信号;
car = new org::example::Examples::CarInterface("", "",
QDBusConnection::sessionBus(), this);
从命令行
dbus-send --session --type=signal /Car org.example.Examples.CarInterface.crashed
干杯,西蒙