You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:08:24