如何使用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
相关产品推荐
相关产品推荐

