常用数据结构
在 GDBus(基于 D-Bus 的通信框架)中,最常用的数据类型主要是通过 GVariant 来表示的。GVariant 是 GLib 提供的一种用于存储任意复杂数据结构的容器类型,它支持多种基础数据类型以及嵌套结构。以下是 GDBus 中最常用的一些数据类型及其对应的 D-Bus 类型代码:
基础数据类型
- 
BYTE (
y)- GLib 数据类型 : 
guchar - 描述: 无符号8位整数 (0-255)
 
 - GLib 数据类型 : 
 - 
BOOLEAN (
b)- GLib 数据类型 : 
gboolean - 描述 : 布尔值,通常为 
TRUE或FALSE 
 - GLib 数据类型 : 
 - 
INT16 (
n)- GLib 数据类型 : 
gint16 - 描述: 有符号16位整数 (-32768到32767)
 
 - GLib 数据类型 : 
 - 
UINT16 (
q)- GLib 数据类型 : 
guint16 - 描述: 无符号16位整数 (0到65535)
 
 - GLib 数据类型 : 
 - 
INT32 (
i)- GLib 数据类型 : 
gint32 - 描述: 有符号32位整数 (-2^31 到 2^31 - 1)
 
 - GLib 数据类型 : 
 - 
UINT32 (
u)- GLib 数据类型 : 
guint32 - 描述: 无符号32位整数 (0到4294967295)
 
 - GLib 数据类型 : 
 - 
INT64 (
x)- GLib 数据类型 : 
gint64 - 描述: 有符号64位整数
 
 - GLib 数据类型 : 
 - 
UINT64 (
t)- GLib 数据类型 : 
guint64 - 描述: 无符号64位整数
 
 - GLib 数据类型 : 
 - 
DOUBLE (
d)- GLib 数据类型 : 
gdouble - 描述: 双精度浮点数
 
 - GLib 数据类型 : 
 - 
STRING (
s)- GLib 数据类型 : 
gchar* - 描述: UTF-8 编码的字符串
 
 - GLib 数据类型 : 
 
复杂数据类型
- 
ARRAY (
a)- 示例 : 
ai表示一个整数数组 - 描述: 包含相同类型的元素集合
 
 - 示例 : 
 - 
VARIANT (
v)- 描述: 可以包含任何其他类型的变体值
 
 - 
DICTIONARY (
a{sv}或a{ss}等)- 示例 : 
a{ss}表示键和值都是字符串的字典 - 描述: 键值对的集合,其中键通常是字符串,值可以是任意类型
 
 - 示例 : 
 - 
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 连接。cGDBusConnection *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 上。cgboolean 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(): 创建一个新的代理对象,用于与远程服务进行通信。cComExampleCalculator *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(): 同步调用远程方法。cgboolean 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(): 发送信号通知客户端。ccom_example_calculator_emit_status_update(object, "Calculation completed."); 
6. 处理信号
- 
g_signal_connect(): 连接信号处理函数。cg_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(): 创建一个新的变体构建器。cGVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("av"));G_VARIANT_TYPE("av"): 指定构建器类型为数组(a)中的变体(v)。
 - 
g_variant_builder_add(): 添加元素到构建器中。cg_variant_builder_add(builder, "{ss}", "location", "file:///tmp/00000001/1.mp3"); - 
g_variant_builder_end(): 完成构建并生成 GVariant 对象。cGVariant *playlist = g_variant_builder_end(builder); 
8. 序列化与反序列化
- 
g_variant_new_from_data(): 根据二进制数据创建 GVariant 对象。cGVariant *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 数组。cGVariantIter *iter = g_variant_iter_new(playlist); - 
g_variant_iter_next(): 遍历 GVariant 数组中的下一个元素。cwhile (g_variant_iter_next(iter, "v", &item)) { // 处理每个 item }