gdbus 常用数据结构与库函数

常用数据结构

在 GDBus(基于 D-Bus 的通信框架)中,最常用的数据类型主要是通过 GVariant 来表示的。GVariant 是 GLib 提供的一种用于存储任意复杂数据结构的容器类型,它支持多种基础数据类型以及嵌套结构。以下是 GDBus 中最常用的一些数据类型及其对应的 D-Bus 类型代码:

基础数据类型

  1. BYTE (y)

    • GLib 数据类型 : guchar
    • 描述: 无符号8位整数 (0-255)
  2. BOOLEAN (b)

    • GLib 数据类型 : gboolean
    • 描述 : 布尔值,通常为 TRUEFALSE
  3. INT16 (n)

    • GLib 数据类型 : gint16
    • 描述: 有符号16位整数 (-32768到32767)
  4. UINT16 (q)

    • GLib 数据类型 : guint16
    • 描述: 无符号16位整数 (0到65535)
  5. INT32 (i)

    • GLib 数据类型 : gint32
    • 描述: 有符号32位整数 (-2^31 到 2^31 - 1)
  6. UINT32 (u)

    • GLib 数据类型 : guint32
    • 描述: 无符号32位整数 (0到4294967295)
  7. INT64 (x)

    • GLib 数据类型 : gint64
    • 描述: 有符号64位整数
  8. UINT64 (t)

    • GLib 数据类型 : guint64
    • 描述: 无符号64位整数
  9. DOUBLE (d)

    • GLib 数据类型 : gdouble
    • 描述: 双精度浮点数
  10. STRING (s)

    • GLib 数据类型 : gchar*
    • 描述: UTF-8 编码的字符串

复杂数据类型

  1. ARRAY (a)

    • 示例 : ai 表示一个整数数组
    • 描述: 包含相同类型的元素集合
  2. VARIANT (v)

    • 描述: 可以包含任何其他类型的变体值
  3. DICTIONARY (a{sv}a{ss} 等)

    • 示例 : a{ss} 表示键和值都是字符串的字典
    • 描述: 键值对的集合,其中键通常是字符串,值可以是任意类型
  4. STRUCTURE (r 或括号形式如 (ii) )

    • 示例 : (is) 表示一个整数和一个字符串组成的结构
    • 描述: 固定顺序的多个值的组合

示例

创建一个简单的 GVariant
c 复制代码
// 创建一个 INT32 类型的 GVariant
GVariant *variant = g_variant_new_int32(42);

// 创建一个 STRING 类型的 GVariant
GVariant *string_variant = g_variant_new_string("Hello, World!");

// 创建一个 ARRAY 类型的 GVariant
GVariantBuilder builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
g_variant_builder_add(&builder, "i", 1);
g_variant_builder_add(&builder, "i", 2);
g_variant_builder_add(&builder, "i", 3);
GVariant *array_variant = g_variant_builder_end(&builder);
使用 GVariant 在 D-Bus 方法调用中传递参数

假设你有一个 D-Bus 接口方法 AddNumbers 需要接收两个整数并返回它们的和:

xml 复制代码
<method name="AddNumbers">
  <arg type="i" name="num1" direction="in"/>
  <arg type="i" name="num2" direction="in"/>
  <arg type="i" name="sum" direction="out"/>
</method>

你可以这样实现客户端调用:

c 复制代码
gint num1 = 5, num2 = 7;
gint sum;
com_example_calculator_call_add_numbers_sync(proxy, num1, num2, &sum, NULL, &error);
if (!error) {
    g_print("Sum: %d\n", sum);
}

而在服务端处理该方法时,可以通过 GVariant 获取输入参数,并设置输出参数:

c 复制代码
static void handle_add_numbers(ComExampleCalculator *object, GDBusMethodInvocation *invocation, gint num1, gint num2) {
    gint sum = num1 + num2;
    com_example_calculator_complete_add_numbers(object, invocation, sum);
}

常用库函数

在使用 GDBus 进行开发时,有几个关键的库函数和工具是经常使用的。这些函数主要用于创建和管理 D-Bus 连接、注册对象、调用远程方法、处理信号等。以下是一些最常用的 GDBus 库函数及其简要说明:

1. 建立连接

  • g_bus_get_sync() : 同步获取一个 D-Bus 连接。

    c 复制代码
    GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
    • G_BUS_TYPE_SESSION: 表示会话总线。
    • NULL: 取消操作的上下文(Cancellable)。
    • &error: 错误信息。

2. 注册对象到 D-Bus 上

  • g_dbus_interface_skeleton_export() : 将接口骨架导出到 D-Bus 上。

    c 复制代码
    gboolean success = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(service), connection, "/com/example/calculator", &error);
    • G_DBUS_INTERFACE_SKELETON(service): 要导出的服务实例。
    • connection: D-Bus 连接。
    • "/com/example/calculator": 对象路径。
    • &error: 错误信息。

3. 创建代理对象

  • com_example_calculator_proxy_new_sync() : 创建一个新的代理对象,用于与远程服务进行通信。

    c 复制代码
    ComExampleCalculator *proxy = com_example_calculator_proxy_new_sync(connection, G_DBUS_PROXY_FLAGS_NONE, "com.example.Calculator", "/com/example/calculator", NULL, &error);

4. 调用远程方法

  • com_example_calculator_call_add_numbers_sync() : 同步调用远程方法。

    c 复制代码
    gboolean success = com_example_calculator_call_add_numbers_sync(proxy, num1, num2, &result, NULL, &error);
    • proxy: 代理对象。
    • num1, num2: 输入参数。
    • &result: 输出结果。
    • NULL: 取消操作的上下文(Cancellable)。
    • &error: 错误信息。

5. 发送信号

  • com_example_calculator_emit_status_update() : 发送信号通知客户端。

    c 复制代码
    com_example_calculator_emit_status_update(object, "Calculation completed.");

6. 处理信号

  • g_signal_connect() : 连接信号处理函数。

    c 复制代码
    g_signal_connect(proxy, "status-update", G_CALLBACK(on_status_update), NULL);
    • proxy: 代理对象。
    • "status-update": 信号名称。
    • G_CALLBACK(on_status_update): 回调函数。
    • NULL: 用户数据。

7. 使用 GVariant 构建复杂数据结构

  • g_variant_builder_new(): 创建一个新的变体构建器。

    c 复制代码
    GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("av"));
    • G_VARIANT_TYPE("av"): 指定构建器类型为数组(a)中的变体(v)。
  • g_variant_builder_add(): 添加元素到构建器中。

    c 复制代码
    g_variant_builder_add(builder, "{ss}", "location", "file:///tmp/00000001/1.mp3");
  • g_variant_builder_end(): 完成构建并生成 GVariant 对象。

    c 复制代码
    GVariant *playlist = g_variant_builder_end(builder);

8. 序列化与反序列化

  • g_variant_new_from_data(): 根据二进制数据创建 GVariant 对象。

    c 复制代码
    GVariant *playlist = g_variant_new_from_data(G_VARIANT_TYPE("av"), data, size, TRUE, NULL, NULL);
    • G_VARIANT_TYPE("av"): 数据类型。
    • data: 二进制数据。
    • size: 数据大小。
    • TRUE: 是否信任数据来源。
  • g_variant_iter_new(): 创建一个新的迭代器用于遍历 GVariant 数组。

    c 复制代码
    GVariantIter *iter = g_variant_iter_new(playlist);
  • g_variant_iter_next(): 遍历 GVariant 数组中的下一个元素。

    c 复制代码
    while (g_variant_iter_next(iter, "v", &item)) {
        // 处理每个 item
    }
相关推荐
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩3 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言