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接口(通過GDBusInterface, GDBusProxy 和 GDBusInterfaceStub 類型)和對象接口(通過GDBusObject, GDBusObjectStub 和 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 (通過 GDBusProxy 類型) 和 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()
andg_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
Owning bus names
Using dbus-glib, you typically call RequestName manually to own a name, like in the following excerpt:
使用dbus-glib來占有一個總線名字的典型做法是手動調用RequestName ,像下面的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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)是更好地方式.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
static void on_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_name_aquired()回調之前導出管理對象,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:
1 2 3 4 |
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:
1 2 3 4 5 6 7 8 9 |
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”