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

纯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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:20:02