使用dbus_message_get_args遍历D-Bus的{a{sv}}字典时出现段错误求解
解决D-Bus消息中
a{sv}字典遍历问题 问题原因
你的代码出现段错误是因为用dbus_message_get_args获取数组迭代器的方式不符合libdbus规范,DBUS_TYPE_ARRAY需要结合元素类型校验,且直接提取迭代器的逻辑有误。另外代码未处理消息的第三个参数,可能导致参数解析错位。
修正后的代码
#include <dbus/dbus.h> #include <stdio.h> #include <string.h> static DBusHandlerResult filter_function(DBusConnection *connection, DBusMessage *message, void *user_data) { // 先验证消息是否为目标信号 if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) { DBusMessageIter msg_iter; if (!dbus_message_iter_init(message, &msg_iter)) { fprintf(stderr, "初始化消息迭代器失败\n"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } // 解析第一个参数:接口名(字符串类型) char *interface_name; if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING) { fprintf(stderr, "第一个参数不是字符串类型\n"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } dbus_message_iter_get_basic(&msg_iter, &interface_name); printf("接口名: %s\n", interface_name); dbus_message_iter_next(&msg_iter); // 解析第二个参数:a{sv}类型的属性字典 if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&msg_iter) != DBUS_TYPE_DICT_ENTRY) { fprintf(stderr, "第二个参数不是a{sv}类型\n"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } DBusMessageIter array_iter; dbus_message_iter_recurse(&msg_iter, &array_iter); // 遍历字典中的每一组键值对 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter entry_iter; dbus_message_iter_recurse(&array_iter, &entry_iter); // 获取键(字符串类型) char *prop_key; if (dbus_message_iter_get_arg_type(&entry_iter) != DBUS_TYPE_STRING) { dbus_message_iter_next(&array_iter); continue; } dbus_message_iter_get_basic(&entry_iter, &prop_key); dbus_message_iter_next(&entry_iter); // 获取值(变体类型,需要递归解析) DBusMessageIter variant_iter; if (dbus_message_iter_get_arg_type(&entry_iter) != DBUS_TYPE_VARIANT) { dbus_message_iter_next(&array_iter); continue; } dbus_message_iter_recurse(&entry_iter, &variant_iter); // 提取Status属性的字符串值 if (strcmp(prop_key, "Status") == 0) { if (dbus_message_iter_get_arg_type(&variant_iter) == DBUS_TYPE_STRING) { char *status_value; dbus_message_iter_get_basic(&variant_iter, &status_value); printf("Status值: %s\n", status_value); } } dbus_message_iter_next(&array_iter); } // 跳过第三个参数:as类型的空属性列表 dbus_message_iter_next(&msg_iter); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
关键修正说明
- 改用
dbus_message_iter_init初始化迭代器,逐步解析每个参数,避免直接用dbus_message_get_args处理复杂类型的错误。 - 严格校验每个参数的类型,确保匹配
sa{sv}as的签名要求。 - 遍历
a{sv}时,先进入数组迭代器,再逐个处理字典条目,每个条目包含键(字符串)和值(变体)。 - 对变体类型的值进行二次递归,提取其中的实际字符串内容。
- 处理完目标参数后跳过第三个空数组参数,避免解析错位。
内容的提问来源于stack exchange,提问作者TwentySix
相关产品推荐
相关产品推荐

