PAYATHON 2026

gdbus-codegen 服务端如何检测客户端写入属性?

数据小许

结论

对于 gdbus-codegen 生成的服务端对象,可以监听对应 GObject 属性的 notify::属性名 信号,获取客户端通过 org.freedesktop.DBus.Properties.Set 写入的值。属性值保存在生成对象中。如果应用还维护自己的状态结构,可以在通知回调中读取新值并同步过去。

监听属性变更

假设生成对象公开了一个名为 Limit 的可写属性。它对应的 GObject 属性名可能会转换为小写形式。请将示例中的 limit 替换为生成代码实际使用的属性名:

static void
on_limit_notify (GObject    *object,
                 GParamSpec *pspec,
                 gpointer    user_data)
{
    MyAppState *state = user_data;
    gint limit;

    g_object_get (object, "limit", &limit, NULL);
    state->limit = limit;
}

/* skeleton 是 gdbus-codegen 生成的服务端对象 */
g_signal_connect (skeleton,
                  "notify::limit",
                  G_CALLBACK (on_limit_notify),
                  &state);

客户端通过 Properties.Set 写入属性后,服务端会更新生成对象中的值,并在属性发生变化时发出对应的 GObject notify 通知。回调随后从生成对象读取新值,并更新应用自己的状态。

如何组织属性状态

如果业务逻辑可以直接使用生成对象中的属性值,就不必另外维护一份状态。若业务代码需要独立的数据结构,可以把生成对象作为 D-Bus 接口的状态入口,再通过属性通知回调同步到该结构,避免两份可写状态出现不一致。

应用自身修改属性时,也应通过生成对象的属性接口更新值,例如:

g_object_set (skeleton, "limit", new_limit, NULL);

这样会更新服务端对象的属性,并由生成代码根据属性的实现处理对外的变更通知。若只修改独立状态结构而不更新生成对象,D-Bus 客户端读到的值可能仍是旧值。

注意事项

  • 确认接口定义中的属性是 readwrite,并使用生成对象实际暴露的 GObject 属性名。可以通过 g_object_class_find_property() 检查属性是否存在。
  • notify::属性名 是 GObject 属性通知,不是通用的“总线属性已变更”回调。如果属性写入没有触发预期通知,请检查生成代码中的属性名称和 setter 实现。
  • 如果应用会把值同步回生成对象,不要在通知回调中无条件地再次设置同一属性,以免产生重复通知或同步循环。

备注:内容仅供参考。