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

如何使用dbus.h构造{String, Variant}字典调用D-Bus的CreateSession方法

解决方案

你需要在创建方法调用消息后、发送请求前,按照D-Bus类型规则追加两个参数,修改后的完整可运行代码如下:

// 编译前请执行:sudo apt-get install -y libdbus-1-dev
// 编译命令:gcc -o test -Wall test.c `pkg-config --cflags dbus-1` `pkg-config --libs dbus-1`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
 
int main() {
    DBusConnection *sesBusCon;
    DBusError error;
    DBusMessage *call;
    DBusMessage *reply;

    dbus_error_init(&error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "初始化错误: %s\n", error.message);
        dbus_error_free(&error);
        return 1;
    }
    
    sesBusCon = dbus_bus_get(DBUS_BUS_SESSION, &error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "连接会话总线失败: %s\n", error.message);
        dbus_error_free(&error);
        return 1;
    }
    
    call = dbus_message_new_method_call("org.bluez.obex", "/org/bluez/obex", "org.bluez.obex.Client1", "CreateSession");     
    if (!call) {
        fprintf(stderr, "创建方法调用消息失败\n");
        return 1;
    }

    // ========== 追加参数开始 ==========
    // 1. 追加第一个参数:目标设备MAC地址
    const char *dest_mac = "D0:9C:7A:A1:A4:63";
    if (!dbus_message_append_args(call, DBUS_TYPE_STRING, &dest_mac, DBUS_TYPE_INVALID)) {
        fprintf(stderr, "追加MAC地址参数失败\n");
        return 1;
    }

    DBusMessageIter args_iter, array_iter, dict_iter, variant_iter;
    dbus_message_iter_init_append(call, &args_iter);

    // 2. 构造第二个参数:a{sv} 类型的字典
    // 打开数组容器(字典本质是元素为键值对的数组)
    if (!dbus_message_iter_open_container(&args_iter, DBUS_TYPE_ARRAY, "{sv}", &array_iter)) {
        fprintf(stderr, "打开数组容器失败\n");
        return 1;
    }

    // 打开字典条目容器(每个键值对是一个{sv}结构)
    if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter)) {
        fprintf(stderr, "打开字典条目容器失败\n");
        return 1;
    }

    // 写入字典的键:字符串 "Target"
    const char *dict_key = "Target";
    dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &dict_key);

    // 打开变体容器,指定变体内部类型为字符串
    if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
        fprintf(stderr, "打开变体容器失败\n");
        return 1;
    }

    // 写入变体的值:字符串 "OPP"
    const char *target_val = "OPP";
    dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &target_val);

    // 逐层关闭所有容器,必须和打开顺序相反
    dbus_message_iter_close_container(&dict_iter, &variant_iter);
    dbus_message_iter_close_container(&array_iter, &dict_iter);
    dbus_message_iter_close_container(&args_iter, &array_iter);
    // ========== 追加参数结束 ==========
    
    reply = dbus_connection_send_with_reply_and_block (sesBusCon, call, 100000, &error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "调用方法失败: %s\n", error.message);
        dbus_error_free(&error);
        return 1;
    }

    // 解析返回的session对象路径
    const char *session_path;
    if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session_path, DBUS_TYPE_INVALID)) {
        printf("Session创建成功,对象路径: %s\n", session_path);
    }

    // 释放资源
    dbus_message_unref(call);
    dbus_message_unref(reply);
    dbus_connection_unref(sesBusCon);
    dbus_error_free(&error);
    
    return 0;
}

核心构造逻辑说明

  • 你要构造的{String, Variant}字典在原生D-Bus协议中对应类型签名a{sv},本质是元素为键-值结构的数组,其中键固定为字符串类型,值为变体类型
  • 所有通过dbus_message_iter_open_container打开的容器必须成对调用dbus_message_iter_close_container关闭,关闭顺序和打开顺序相反,否则参数构造会直接失败
  • 如果需要添加更多字典条目,只需重复打开字典条目容器、写入键、写入变体值、关闭字典条目容器的流程即可

内容的提问来源于stack exchange,提问作者TwentySix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:39:03