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 实现。- 如果应用会把值同步回生成对象,不要在通知回调中无条件地再次设置同一属性,以免产生重复通知或同步循环。
备注:内容仅供参考。
