QT D-Bus 复杂参数传递
网上一搜,关于D-Bus和QT的资料不少,但是绝大多数都对传递自定义数据类型这个问题闭口不谈。看来这个有必要写个文章记录一下。
首先要说的是,我这里不再介绍D-Bus和QDbus的基础知识,本文直击要点。另外本文参考了KDE的一些文档。
需求:使用标准的信号和槽,通过QDBus传递自定义的struct或者class数据类型。
首先,需要定义需要通过D-Bus传递的自定义数据类型,我们这里定义一个Message类型:
#include <QtDBus>
class Message
{
public:构造函数等略
friend QDBusArgument &operator<<(QDBusArgument &argument, const Message &message);
friend const QDBusArgument &operator>>(const QDBusArgument &argument, Message &message);
static void registerMetaType();
private:
QString m_strMessage;
};
Q_DECLARE_METATYPE(Message)
可以看到有几个比较特殊的地方:
首先我们重载了<<和>>两个运算符,这是将自定义数据类型融合到QT的类型系统所必需的:
QDBusArgument &operator<<(QDBusArgument &argument, const Message& message)
{
argument.beginStructure();
argument << message.m_strMessage;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, Message &message)
{
argument.beginStructure();
argument >> message.m_strMessage;
argument.endStructure();
return argument;
}
其次,这个自定义数据类型需要注册到QT和D-Bus的类型系统:
void Message::registerMetaType()
{qRegisterMetaType<Message>("Message");
qDBusRegisterMetaType<Message>();
}
有了这个数据类型,就可以写描述D-Bus接口的XML文件了:
<!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="demo.Action">
<signal name="messageSent">
<arg name="message" type="a(i)" direction="out"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="Message"/>
</signal>
<method name="sendMessage">
<arg name="message" type="a(i)" direction="in"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="Message"/>
</method>
</interface>
</node>
这里有两个特殊点,一个是参数的数据类型,因为是我们自定义的,不存在于D-Bus规范中,所以参数的type在这里可以乱写。另一个就是,既然是自定义的,就要说明这个自定义的数据类型到底是啥(在这里是Message)。
OK,有了上面这些啰嗦的准备工作,下面调用QT自带的D-Bus工具,就可以自动生成相关的接口和代理类了:
qdbusxml2cpp Chat.xml -i Message.h -a MessageAdaptor
qdbusxml2cpp Chat.xml -i Message.h -p MessageInterface
后续就是标准的调用QDBus过程了,本文不再废话,请参考其他入门资料。大体上就是这样:
接收:
connect(&m_MessageInterface, SIGNAL(messageSent(Message)), SLOT(onMessageSent(Message)));
发送:
Message message(…);
m_MessageInterface.sendMessage(message);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构