// 必要的头文件
#include <QDBusMessage>
#include <QDBusInterface>
#include <QDBusReply>
// 定义D-Bus的接口
QDBusInterface interface = new QDBusInterface("com.deepin.dde.Launcher",
"/com/deepin/dde/Launcher",
"com.deepin.dde.Launcher",
QDBusConnection::sessionBus());
// 调用D-Bus接口的方法
QDBusMessage msg = interface->call(QDBus::Block, "IsVisible");
// 查看D-Bus方法的返回值
QList<QVariant> received = msg.arguments();
// 重载了QDBusReply::operator=,所以下面的写法也是可以的,
// 一个QDBusReply对象是方法调用的应答QDBusMessage对象的一个子集,QDBusReply对象只包含第一个输出参数或错误代码。
// QDBusReply<bool> reply = interface->call(QDBus::Block, "IsVisible");
// qInfo() << reply.value();
// 必要的头文件
#include <QDBusPendingReply>
#include <QDBusInterface>
#include <QDBusPendingCallWatcher>
// 定义D-Bus的接口
QDBusInterface interface = new QDBusInterface("com.deepin.dde.Launcher",
"/com/deepin/dde/Launcher",
"com.deepin.dde.Launcher",
QDBusConnection::sessionBus());
// 调用D-Bus接口的方法
QDBusPendingCall pcall = interface->asyncCall("IsVisible");
// 设置等待异步消息的信号槽
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, nullptr);
QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &MainWindow::slotDBusCallFinished);
// 处理异步D-Bus消息返回值的槽函数
void MainWindow::slotDBusCallFinished(QDBusPendingCallWatcher *wather)
{
// 根据消息返回值类型定义QDBusPendingReply
QDBusPendingReply<bool> reply = *wather;
bool isVisable = reply.argumentAt<0>();
wather->deleteLater();
qInfo() << isVisable;
}
此方法适用场景为不关心返回值。
// 必要的头文件
#include <QDBusMessage>
#include <QDBusConnection>
// 构造消息体
QDBusMessage msg = QDBusMessage::createMethodCall("com.deepin.dde.Launcher",
"/com/deepin/dde/Launcher",
"com.deepin.dde.Launcher",
"Show");
// Sends the message over this connection, without waiting for a reply.
// This is suitable for errors, signals,
// and return values as well as calls whose return values are not necessary.
// 发送消息
QDBusConnection::sessionBus().send(msg);
需要使用Qt4的SLOT宏将响应信号的槽函数包起来。
// 必要的头文件
#include <QDBusMessage>
QDBusConnection::sessionBus().connect("com.deepin.dde.Launcher",
"/com/deepin/dde/Launcher",
"com.deepin.dde.Launcher",
"VisibleChanged",
this,
SLOT(slotVisibleChanged(bool)));
如果使用命令行方式测试信号是否能被接收,需要修改上述代码,将D-Bus名称,D-Bus路径,D-Bus接口这些参数全部赋空。
// 必要的头文件
#include <QDBusMessage>
QDBusConnection::sessionBus().connect("", "", "",
"VisibleChanged", this, SLOT(slotVisibleChanged(bool)));
对应的测试命令如下。
dbus-send --session --type=signal /com/deepin/dde/Launcher com.deepin.dde.Launcher.VisibleChanged boolean:false
参考文档
因为用到了Qt的MOC机制,所以下面的类定义一定要放在头文件中(也可以手动执行moc命令生成moc_xxx.cpp文件)。否则会有undefined reference to vtable的错误。
class DBusDemo: public QObject
{
Q_OBJECT
// 定义D-Bus服务名称
Q_CLASSINFO("D-Bus Interface", "org.example.QDBusDemo")
// 申明属性
Q_PROPERTY(QString nickname READ nickname WRITE setNickname MEMBER myNickname)
public:
explicit DBusDemo(QObject *parent = nullptr): QObject(parent) {}
// 属性-读
QString nickname() { return myNickname; }
// 属性-写
void setNickname(QString name){ myNickname = name; }
public slots:
// D-Bus方法
QDBusVariant helloJerry(const QString &name) { return QDBusVariant("Hello " + name); }
signals:
// D-Bus信号
void sayHello();
private:
QString myNickname = "Jerry";
};
通过D-Bus实现单例模式。
DBusDemo dbusDemo;
QDBusConnection dbus = QDBusConnection::sessionBus();
// 尝试注册D-Bus服务,如果注册成功,表示应用没有启动,启动应用。
// 如果注册失败,则说明应用已经启动了,调用接口,让已启动的应用去完成任务。
if (dbus.registerService("org.example.QDBusDemo")) {
dbus.registerObject("/org/example/QDBusDemo",
&dbusDemo,
QDBusConnection::ExportAllSlots
| QDBusConnection::ExportAllProperties
| QDBusConnection::ExportAllSignals);
// TODO 启动APP等逻辑
} else {
// TODO 通过上述D-Bus方法调用本服务的接口完成业务逻辑
}
简单使用,参考上述用法即可,深度使用D-Bus,可使用该模式。
参考Qt的官方例子,D-Bus Complex Ping Pong Example,自行百度。