2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
4 <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
5 <!ENTITY version SYSTEM "version.xml">
8 <title>Migrating to GDBus</title>
11 <title>Conceptual differences</title>
14 The central concepts of D-Bus are modelled in a very similar way
15 in dbus-glib and GDBus. Both have a objects representing connections,
16 proxies and method invocations. But there are some important
20 dbus-glib uses the <ulink
21 url="http://www.freedesktop.org/wiki/Software/dbus#ReferenceImplementation.28dbus-daemonandlibdbus.29">libdbus
22 reference implementation</ulink>, GDBus doesn't. Instead, it
23 relies on GIO streams as transport layer, and has its own
24 implementation for the D-Bus connection setup and
25 authentication. Apart from using streams as transport,
26 avoiding libdbus also lets GDBus avoid some thorny
27 multithreading issues.
30 dbus-glib uses the GObject type system for method arguments and
31 return values, including a homegrown container specialization
32 mechanism. GDBus relies on the #GVariant type system which is
33 explicitly designed to match D-Bus types.
36 dbus-glib models only D-Bus interfaces and does not provide
37 any types for objects. GDBus models both D-Bus interfaces
38 (via the #GDBusInterface, #GDBusProxy and
39 #GDBusInterfaceSkeleton types) and objects (via the
40 #GDBusObject, #GDBusObjectSkeleton and #GDBusObjectProxy types).
43 GDBus includes native support for the <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.DBus.Properties</ulink> (via the #GDBusProxy type) and <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.DBus.ObjectManager</ulink> D-Bus interfaces, dbus-glib doesn't.
46 The typical way to export an object in dbus-glib involves
47 generating glue code from XML introspection data using
48 <command>dbus-binding-tool</command>. GDBus provides a
49 similar tool called <command><link
50 linkend="gdbus-codegen">gdbus-codegen</link></command> that
51 can also generate Docbook D-Bus interface documentation.
54 dbus-glib doesn't provide any convenience API for owning and
55 watching bus names, GDBus provides the g_bus_own_name() and
56 g_bus_watch_name() family of convenience functions.
59 GDBus provides API to parse, generate and work with <link
60 linkend="gio-D-Bus-Introspection-Data">Introspection
61 XML</link>, dbus-glib doesn't.
64 GTestDBus provides API to create isolated unit tests <link
65 linkend="gio-D-Bus-Test-Scaffolding">GDBus Test Scaffolding</link>.
72 <title>API comparison</title>
74 <table id="dbus-glib-vs-gdbus">
75 <title>dbus-glib APIs and their GDBus counterparts</title>
78 <row><entry>dbus-glib</entry><entry>GDBus</entry></row>
81 <row><entry>#DBusGConnection</entry><entry>#GDBusConnection</entry></row>
82 <row><entry>#DBusGProxy</entry><entry>#GDBusProxy, #GDBusInterface - also see #GDBusObjectProxy</entry></row>
83 <row><entry>#DBusGObject</entry><entry>#GDBusInterfaceSkeleton, #GDBusInterface - also see #GDBusObjectSkeleton</entry></row>
84 <row><entry>#DBusGMethodInvocation</entry><entry>#GDBusMethodInvocation</entry></row>
85 <row><entry>dbus_g_bus_get()</entry><entry>g_bus_get_sync(), also see
86 g_bus_get()</entry></row>
87 <row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync() and
88 g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()</entry></row>
89 <row><entry>dbus_g_proxy_add_signal()</entry><entry>not needed, use the generic #GDBusProxy::g-signal</entry></row>
90 <row><entry>dbus_g_proxy_connect_signal()</entry><entry>use g_signal_connect() with #GDBusProxy::g-signal</entry></row>
91 <row><entry>dbus_g_connection_register_g_object()</entry><entry>g_dbus_connection_register_object() - also see g_dbus_object_manager_server_export()</entry></row>
92 <row><entry>dbus_g_connection_unregister_g_object()</entry><entry>g_dbus_connection_unregister_object() - also see g_dbus_object_manager_server_unexport()</entry></row>
93 <row><entry>dbus_g_object_type_install_info()</entry><entry>introspection data is installed while registering
94 an object, see g_dbus_connection_register_object()</entry></row>
95 <row><entry>dbus_g_proxy_begin_call()</entry><entry>g_dbus_proxy_call()</entry></row>
96 <row><entry>dbus_g_proxy_end_call()</entry><entry>g_dbus_proxy_call_finish()</entry></row>
97 <row><entry>dbus_g_proxy_call()</entry><entry>g_dbus_proxy_call_sync()</entry></row>
98 <row><entry>dbus_g_error_domain_register()</entry><entry>g_dbus_error_register_error_domain()</entry></row>
99 <row><entry>dbus_g_error_has_name()</entry><entry>no direct equivalent, see g_dbus_error_get_remote_error()</entry></row>
100 <row><entry>dbus_g_method_return()</entry><entry>g_dbus_method_invocation_return_value()</entry></row>
101 <row><entry>dbus_g_method_return_error()</entry><entry>g_dbus_method_invocation_return_error() and variants</entry></row>
102 <row><entry>dbus_g_method_get_sender()</entry><entry>g_dbus_method_invocation_get_sender()</entry></row>
109 <title>Owning bus names</title>
111 Using dbus-glib, you typically call RequestName manually
112 to own a name, like in the following excerpt:
113 <informalexample><programlisting><![CDATA[
115 res = dbus_g_proxy_call (system_bus_proxy,
118 G_TYPE_STRING, NAME_TO_CLAIM,
119 G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
121 G_TYPE_UINT, &result,
127 g_warning ("Failed to acquire %s: %s",
128 NAME_TO_CLAIM, error->message);
129 g_error_free (error);
133 g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
138 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
142 g_warning ("Failed to acquire %s: %s",
143 NAME_TO_CLAIM, error->message);
144 g_error_free (error);
148 g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
153 dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",
154 G_TYPE_STRING, G_TYPE_INVALID);
155 dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",
156 G_CALLBACK (on_name_lost), NULL, NULL);
158 /* further setup ... */
160 </programlisting></informalexample>
163 While you can do things this way with GDBus too, using
164 g_dbus_proxy_call_sync(), it is much nicer to use the high-level API
166 <informalexample><programlisting><![CDATA[
168 on_name_acquired (GDBusConnection *connection,
172 /* further setup ... */
177 owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
179 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
186 g_main_loop_run (loop);
188 g_bus_unown_name (owner_id);
190 </programlisting></informalexample>
191 Note that g_bus_own_name() works asynchronously and requires
192 you to enter your mainloop to await the on_name_aquired()
193 callback. Also note that in order to avoid race conditions (e.g.
194 when your service is activated by a method call), you have to export
195 your manager object <emphasis>before</emphasis> acquiring the
196 name. The on_bus_acquired() callback is the right place to do
202 <title>Creating proxies for well-known names</title>
204 dbus-glib lets you create proxy objects for well-known names, like the
206 <informalexample><programlisting><![CDATA[
207 proxy = dbus_g_proxy_new_for_name (system_bus_connection,
208 "org.freedesktop.Accounts",
209 "/org/freedesktop/Accounts",
210 "org.freedesktop.Accounts");
212 </programlisting></informalexample>
213 For a #DBusGProxy constructed like this, method calls will be sent to
214 the current owner of the name, and that owner can change over time.
217 The same can be achieved with #GDBusProxy:
218 <informalexample><programlisting><![CDATA[
220 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
221 G_DBUS_PROXY_FLAGS_NONE,
222 NULL, /* GDBusInterfaceInfo */
223 "org.freedesktop.Accounts",
224 "/org/freedesktop/Accounts",
225 "org.freedesktop.Accounts",
226 NULL, /* GCancellable */
229 </programlisting></informalexample>
230 For an added layer of safety, you can specify what D-Bus
231 interface the proxy is expected to conform to by using the
232 #GDBusInterfaceInfo type. Additionally, #GDBusProxy loads,
233 caches and tracks changes to the D-Bus properties on the remote
234 object. It also sets up match rules so D-Bus signals from the
235 remote object are delivered locally.
238 The #GDBusProxy type normally isn't used directly - instead
239 proxies subclassing #GDBusProxy generated by <command><link
240 linkend="gdbus-codegen">gdbus-codegen</link></command> is used, see <xref linkend="gdbus-example-gdbus-codegen"/>
244 <section id="gdbus-example-gdbus-codegen">
245 <title>Using gdbus-codegen</title>
248 dbus-glib comes with <command>dbus-binding-tool</command>, which
249 can produce somewhat nice client- and server-side wrappers for a D-Bus interface.
250 With GDBus, <command><link
251 linkend="gdbus-codegen">gdbus-codegen</link></command> is used and like
252 its counterpart, it also takes D-Bus Introspection XML as input:
254 <example id="gdbus-example-codegen-input"><title>Example D-Bus Introspection XML</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../gdbus-example-objectmanager.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
256 If this XML is processed like this
257 <informalexample><programlisting><![CDATA[
258 gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
259 --generate-c-code generated-code \
260 --c-namespace Example \
261 --c-generate-object-manager \
262 --generate-docbook generated-docs \
263 gdbus-example-objectmanager.xml
264 ]]></programlisting></informalexample>
265 then two files <filename>generated-code.h</filename> and
266 <filename>generated-code.c</filename> are
267 generated. Additionally, two XML files
268 <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal</filename> and
269 <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat</filename>
270 with Docbook XML are generated.
273 While the contents of <filename>generated-code.h</filename> and
274 <filename>generated-code.c</filename> are best described by the
276 linkend="gdbus-codegen">gdbus-codegen</link></command> manual
277 page, brief examples of how this generated code can be used can be found in
278 <xref linkend="gdbus-example-codegen-server"/>
279 and <xref linkend="gdbus-example-codegen-client"/>.