首页 > 代码库 > dbus-glib 和 GDBus 的区别

dbus-glib 和 GDBus 的区别

http://people.freedesktop.org/~david/gio-gdbus-codegen-20110412/ch29.html

Conceptual differences

The central concepts of D-Bus are modelled in a very similar way in dbus-glib and GDBus. Both have a objects representing connections, proxies and method invocations. But there are some important differences:

D-Bus最重要的概念在dbus-glib和GDBus中都是相似的.都用对象表示连接,代理 和 方法执行,但也有一些重要的不同点:

  • dbus-glib uses the libdbus reference implementation, GDBus doesn‘t. Instead, it relies on GIO streams as transport layer, and has its own implementation for the the D-Bus connection setup and authentication. Apart from using streams as transport, avoiding libdbus also lets GDBus avoid some thorny multithreading issues.

        dbus-glib使用 libdbus reference implementation,GDBus不使用,而是依赖GIO流作为传输层,并且拥有一套自己实现的D-Bus连接设置和授权的方法.暂且不说GDBus使用流传输,

        不使用libdbus可以使GDBus没有一些多线程方面的问题.

  • dbus-glib uses the GObject type system for method arguments and return values, including a homegrown container specialization mechanism. GDBus relies on the GVariant type system which is explicitly designed to match D-Bus types.

       dbus-glib的方法参数和返回值使用Gobject类型系统,其中包含了一个特定结构的自有容器.GDBus依赖专为匹配D-Bus类型而设计的GVariant类型系统

  • dbus-glib models only D-Bus interfaces and does not provide any types for objects. GDBus models both D-Bus interfaces (via the GDBusInterface, GDBusProxy and GDBusInterfaceStub types) and objects (via the GDBusObject, GDBusObjectStub and GDBusObjectProxy types).

       dbus-glib 只能提供D-Bus接口,不为对象提供任何类型,

       GDBus同时提供D-Bus接口(通过GDBusInterfaceGDBusProxy 和 GDBusInterfaceStub 类型)和对象(通过GDBusObjectGDBusObjectStub 和 GDBusObjectProxy 类型)

  • GDBus includes native support for the org.freedesktop.DBus.Properties (via the GDBusProxy type) and org.freedesktop.DBus.ObjectManager D-Bus interfaces, dbus-glib doesn‘t.

       GDBus 为org.freedesktop.DBus.Properties (via the GDBusProxy type) 和 org.freedesktop.DBus.ObjectManager D-Bus接口,包含了本地支持,dbus-glib没有.

  • The typical way to export an object in dbus-glib involves generating glue code from XML introspection data using dbus-binding-tool. GDBus provides a similar tool called gdbus-codegen that can also generate Docbook D-Bus interface documentation. 

       dbus-glib中导出对象的典型方法是使用dbus-binding-tool根据XML内省数据生成代码,GDBus也提供了一个类似的工具叫做gdbus-codegen,这个工具也可以生成Docbook D-Bus接口文件.        

  • dbus-glib doesn‘t provide any convenience API for owning and watching bus names, GDBus provides the g_bus_own_name() and g_bus_watch_name() family of convenience functions.

       dbus-glib不提供战友和监视总线名字的方便的API,GDBus提供了g_bus_own_name() 和g_bus_watch_name() 系列的方便函数.

  • GDBus provides API to parse, generate and work with Introspection XML, dbus-glib doesn‘t.

        GDBus提供API来解析、生成 和 工作的内省XML,dbus-glib不提供。

 

API comparison

                        Table. dbus-glib APIs and their GDBus counterparts

dbus-glibGDBus
DBusGConnectionGDBusConnection
DBusGProxyGDBusProxy, GDBusInterface - also see GDBusObjectProxy
DBusGObjectGDBusInterfaceStub, GDBusInterface - also see GDBusObjectStub
DBusGMethodInvocationGDBusMethodInvocation
dbus_g_bus_get()g_bus_get_sync(), also see g_bus_get()
dbus_g_proxy_new_for_name()g_dbus_proxy_new_sync() and g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()
dbus_g_proxy_add_signal()not needed, use the generic "g-signal"
dbus_g_proxy_connect_signal()use g_signal_connect() with "g-signal"
dbus_g_connection_register_g_object()g_dbus_connection_register_object() - also see g_dbus_object_manager_server_export()
dbus_g_connection_unregister_g_object()g_dbus_connection_unregister_object() - also see g_dbus_object_manager_server_unexport()
dbus_g_object_type_install_info()introspection data is installed while registering an object, see g_dbus_connection_register_object()
dbus_g_proxy_begin_call()g_dbus_proxy_call()
dbus_g_proxy_end_call()g_dbus_proxy_call_finish()
dbus_g_proxy_call()g_dbus_proxy_call_sync()
dbus_g_error_domain_register()g_dbus_error_register_error_domain()
dbus_g_error_has_name()no direct equivalent, see g_dbus_error_get_remote_error()
dbus_g_method_return()g_dbus_method_invocation_return_value()
dbus_g_method_return_error()g_dbus_method_invocation_return_error() and variants
dbus_g_method_get_sender()g_dbus_method_invocation_get_sender()

 

Owning bus names

Using dbus-glib, you typically call RequestName manually to own a name, like in the following excerpt:

使用dbus-glib来占有一个总线名字的典型做法是手动调用RequestName ,像下面的例子:

123456789101112131415161718192021222324252627282930313233343536373839404142434445
error = NULL;res = dbus_g_proxy_call (system_bus_proxy,                         "RequestName",                         &error,                         G_TYPE_STRING, NAME_TO_CLAIM,                         G_TYPE_UINT,   DBUS_NAME_FLAG_ALLOW_REPLACEMENT,                         G_TYPE_INVALID,                         G_TYPE_UINT,   &result,                         G_TYPE_INVALID);if (!res)  {    if (error != NULL)      {        g_warning ("Failed to acquire %s: %s",                   NAME_TO_CLAIM, error->message);        g_error_free (error);      }    else      {        g_warning ("Failed to acquire %s", NAME_TO_CLAIM);      }    goto out;  }if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {    if (error != NULL)      {        g_warning ("Failed to acquire %s: %s",                   NAME_TO_CLAIM, error->message);        g_error_free (error);      }    else      {        g_warning ("Failed to acquire %s", NAME_TO_CLAIM);      }    exit (1);  }dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",                         G_TYPE_STRING, G_TYPE_INVALID);dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",                             G_CALLBACK (on_name_lost), NULL, NULL);/* further setup ... */

 

While you can do things this way with GDBus too, using g_dbus_proxy_call_sync(), it is much nicer to use the high-level API for this:

当然你可以使用GDBus的方式,调用函数g_dbus_proxy_call_sync()来完成同样的功能,但是使用高级的API(g_bus_own_name)是更好地方式.

12345678910111213141516171819202122
static voidon_name_acquired (GDBusConnection *connection,                  const gchar     *name,                  gpointer         user_data){  /* further setup ... */}/* ... */  owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,                             NAME_TO_CLAIM,                             G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,                             on_bus_acquired,                             on_name_acquired,                             on_name_lost,                             NULL,                             NULL);  g_main_loop_run (loop);  g_bus_unown_name (owner_id);

Note that g_bus_own_name() works asynchronously and requires you to enter your mainloop to await the on_name_aquired() callback. Also note that in order to avoid race conditions (e.g. when your service is activated by a method call), you have to export your manager object before acquiring the name. The on_bus_acquired() callback is the right place to do such preparations.

需要注意的是g_bus_own_name 工作方式是异步的,并且需要你进入mainloop来等待on_name_aquired()这个callback被调用.还需要注意的是为了防止条件竞争(例如你的服务是同方法调用来启动的),你必须在就收名字之前导出管理对象,on_bus_acquired()这个callback中是导出管理对象的正确位置.

Creating proxies for well-known names

dbus-glib lets you create proxy objects for well-known names, like the following example:

1234
proxy = dbus_g_proxy_new_for_name (system_bus_connection,                                   "org.freedesktop.Accounts",                                   "/org/freedesktop/Accounts",                                   "org.freedesktop.Accounts");

For a DBusGProxy constructed like this, method calls will be sent to the current owner of the name, and that owner can change over time.

The same can be achieved with GDBusProxy:

123456789
error = NULL;proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,                                       G_DBUS_PROXY_FLAGS_NONE,                                       NULL, /* GDBusInterfaceInfo */                                       "org.freedesktop.Accounts",                                       "/org/freedesktop/Accounts",                                       "org.freedesktop.Accounts",                                       NULL, /* GCancellable */                                       &error);

For an added layer of safety, you can specify what D-Bus interface the proxy is expected to conform to by using the GDBusInterfaceInfo type. Additionally, GDBusProxy loads, caches and tracks changes to the D-Bus properties on the remote object. It also sets up match rules so D-Bus signals from the remote object are delivered locally.

The GDBusProxy type normally isn‘t used directly - instead proxies subclassing GDBusProxy generated by gdbus-codegen is used, see the section called “Using gdbus-codegen”