如何用C++从sd-bus容器中获取不同类型的DBus数据
处理DBus.Properties.GetAll返回值中Variant类型的方法
你已经正确进入了数组和dict条目容器,接下来处理variant的核心是先获取variant的类型签名,再根据签名读取对应的值,具体步骤如下:
读取dict的键(字符串类型):
使用sd_bus_message_read(reply, "s", &key)获取属性名,key是提前声明的const char*变量。处理variant部分:
- 调用
sd_bus_message_enter_container(reply, 'v', NULL)进入variant容器,第二个参数传NULL让函数自动获取variant的类型签名。 - 获取variant的类型签名:用
sd_bus_message_get_signature(reply, true)得到当前variant内值的类型字符串,比如s(字符串)、as(字符串数组)等。 - 根据类型签名分支处理:
- 字符串类型(签名
s):用sd_bus_message_read(reply, "s", &str_val)读取。 - 字符串数组类型(签名
as):先调用sd_bus_message_enter_container(reply, 'a', 's')进入数组,再循环用sd_bus_message_read(reply, "s", &elem)读取每个元素,读完后调用sd_bus_message_exit_container(reply)退出数组。 - 其他类型(布尔、整数等)同理,对应DBus类型签名调用读取方法即可。
- 字符串类型(签名
- 调用
sd_bus_message_exit_container(reply)退出variant容器。
- 调用
退出当前dict条目容器:调用
sd_bus_message_exit_container(reply),然后循环处理下一个dict条目,直到数组处理完毕。
以下是简化的代码片段示例:
const char *key; // 读取dict的键 if (sd_bus_message_read(reply, "s", &key) < 0) { // 错误处理逻辑 } // 进入variant容器 if (sd_bus_message_enter_container(reply, 'v', NULL) < 0) { // 错误处理逻辑 } // 获取variant的类型签名 const char *sig = sd_bus_message_get_signature(reply, true); if (!sig) { // 错误处理逻辑 } if (strcmp(sig, "s") == 0) { const char *str_val; sd_bus_message_read(reply, "s", &str_val); // 处理字符串值 } else if (strcmp(sig, "as") == 0) { if (sd_bus_message_enter_container(reply, 'a', 's') < 0) { // 错误处理逻辑 } const char *elem; while (sd_bus_message_read(reply, "s", &elem) > 0) { // 处理每个字符串元素 } sd_bus_message_exit_container(reply); } // 可添加更多类型的处理分支 // 退出variant容器 sd_bus_message_exit_container(reply); // 退出当前dict条目容器 sd_bus_message_exit_container(reply);
注意:每次进入容器后必须对应调用退出容器的函数,避免消息指针错位;所有sd_bus系列函数的返回值需检查,小于0表示调用出错,需添加对应的错误处理逻辑。
内容的提问来源于stack exchange,提问作者안성현
相关产品推荐
相关产品推荐

