纯C语言通过DBus收发二进制数据的实现教程及代码疑问
纯C环境下通过DBus收发二进制数据实现方案
核心说明
DBus中没有直接的"无类型内存块"类型,二进制数据需封装为字节数组(array of bytes),对应DBus类型签名为ay(a表示数组,y表示字节)。以下是符合需求的实现代码,同时修正原代码中的错误:
- 不能用
dbus_message_new(DBUS_TYPE_ARRAY)创建消息,需创建具体的消息类型(如方法调用、信号) - 释放消息需用
dbus_message_unref(),而非dbus_free()(后者用于释放普通内存块)
完整实现代码
#include <dbus/dbus.h> #include <string.h> // 发送二进制数据(以方法调用为例,可根据需求改为信号) void write_msg(DBusConnection *conn, void *data, size_t datasize) { if (!conn || !data || datasize == 0) return; // 创建方法调用消息:需替换为你的服务名、对象路径、接口名、方法名 DBusMessage *msg = dbus_message_new_method_call( "com.example.MyService", // 目标服务名 "/com/example/MyObject", // 目标对象路径 "com.example.MyInterface", // 接口名 "SendBinaryData" // 方法名 ); if (!msg) return; DBusMessageIter iter, array_iter; // 初始化消息迭代器 dbus_message_iter_init_append(msg, &iter); // 打开字节数组类型的子迭代器(签名"ay") if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &array_iter)) { dbus_message_unref(msg); return; } // 将二进制数据写入数组迭代器 dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, &data, datasize); // 关闭数组迭代器 dbus_message_iter_close_container(&iter, &array_iter); // 发送消息,不等待回复 dbus_connection_send(conn, msg, NULL); // 释放消息引用 dbus_message_unref(msg); } // 接收二进制数据 void read_msg(DBusConnection *conn, void *data, size_t datasize) { if (!conn || !data || datasize == 0) return; DBusMessage *msg = dbus_connection_pop_message(conn); if (!msg) return; // 校验消息类型和接口(可选,根据实际需求添加) if (dbus_message_is_method_call(msg, "com.example.MyInterface", "SendBinaryData")) { DBusMessageIter iter, array_iter; // 初始化消息迭代器,定位到第一个参数 if (dbus_message_iter_init(msg, &iter)) { // 检查参数类型是否为字节数组 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) { // 打开数组迭代器 dbus_message_iter_recurse(&iter, &array_iter); // 读取字节数组到目标内存块(注意:需确保datasize与实际数据大小匹配) const unsigned char *buf; int len; dbus_message_iter_get_fixed_array(&array_iter, &buf, &len); if ((size_t)len <= datasize) { memcpy(data, buf, len); } } } } // 释放消息引用 dbus_message_unref(msg); } // 使用示例 typedef struct { int id; char name[20]; float value; } my_struct; int main() { DBusConnection *conn; DBusError err; dbus_error_init(&err); // 连接到会话总线(或系统总线DBUS_BUS_SYSTEM) conn = dbus_bus_get(DBUS_BUS_SESSION, &err); if (dbus_error_is_set(&err)) { dbus_error_free(&err); return 1; } // 发送示例 my_struct st = {1, "test", 3.14f}; write_msg(conn, &st, sizeof(st)); // 接收示例(需在事件循环中调用,此处仅为示例) my_struct recv_st; read_msg(conn, &recv_st, sizeof(recv_st)); dbus_connection_unref(conn); return 0; }
关键注意事项
- 消息类型选择:示例用方法调用,若需广播数据可改用
dbus_message_new_signal创建信号消息 - 错误处理:示例简化了错误处理,实际开发中需检查每个DBus函数的返回值,处理
DBusError - 数据大小匹配:接收时需确保目标内存块大小足够容纳发送的二进制数据,避免溢出
- 总线连接:需根据实际场景连接会话总线(
DBUS_BUS_SESSION)或系统总线(DBUS_BUS_SYSTEM)
内容的提问来源于stack exchange,提问作者White Owl
相关产品推荐
相关产品推荐

