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 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.
68 <title>API comparison</title>
70 <table id="dbus-glib-vs-gdbus">
71 <title>dbus-glib APIs and their GDBus counterparts</title>
74 <row><entry>dbus-glib</entry><entry>GDBus</entry></row>
77 <row><entry>#DBusGConnection</entry><entry>#GDBusConnection</entry></row>
78 <row><entry>#DBusGProxy</entry><entry>#GDBusProxy, #GDBusInterface - also see #GDBusObjectProxy</entry></row>
79 <row><entry>#DBusGObject</entry><entry>#GDBusInterfaceSkeleton, #GDBusInterface - also see #GDBusObjectSkeleton</entry></row>
80 <row><entry>#DBusGMethodInvocation</entry><entry>#GDBusMethodInvocation</entry></row>
81 <row><entry>dbus_g_bus_get()</entry><entry>g_bus_get_sync(), also see
82 g_bus_get()</entry></row>
83 <row><entry>dbus_g_proxy_new_for_name()</entry><entry>g_dbus_proxy_new_sync() and
84 g_dbus_proxy_new_for_bus_sync(), also see g_dbus_proxy_new()</entry></row>
85 <row><entry>dbus_g_proxy_add_signal()</entry><entry>not needed, use the generic #GDBusProxy::g-signal</entry></row>
86 <row><entry>dbus_g_proxy_connect_signal()</entry><entry>use g_signal_connect() with #GDBusProxy::g-signal</entry></row>
87 <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>
88 <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>
89 <row><entry>dbus_g_object_type_install_info()</entry><entry>introspection data is installed while registering
90 an object, see g_dbus_connection_register_object()</entry></row>
91 <row><entry>dbus_g_proxy_begin_call()</entry><entry>g_dbus_proxy_call()</entry></row>
92 <row><entry>dbus_g_proxy_end_call()</entry><entry>g_dbus_proxy_call_finish()</entry></row>
93 <row><entry>dbus_g_proxy_call()</entry><entry>g_dbus_proxy_call_sync()</entry></row>
94 <row><entry>dbus_g_error_domain_register()</entry><entry>g_dbus_error_register_error_domain()</entry></row>
95 <row><entry>dbus_g_error_has_name()</entry><entry>no direct equivalent, see g_dbus_error_get_remote_error()</entry></row>
96 <row><entry>dbus_g_method_return()</entry><entry>g_dbus_method_invocation_return_value()</entry></row>
97 <row><entry>dbus_g_method_return_error()</entry><entry>g_dbus_method_invocation_return_error() and variants</entry></row>
98 <row><entry>dbus_g_method_get_sender()</entry><entry>g_dbus_method_invocation_get_sender()</entry></row>
105 <title>Owning bus names</title>
107 Using dbus-glib, you typically call RequestName manually
108 to own a name, like in the following excerpt:
109 <informalexample><programlisting><![CDATA[
111 res = dbus_g_proxy_call (system_bus_proxy,
114 G_TYPE_STRING, NAME_TO_CLAIM,
115 G_TYPE_UINT, DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
117 G_TYPE_UINT, &result,
123 g_warning ("Failed to acquire %s: %s",
124 NAME_TO_CLAIM, error->message);
125 g_error_free (error);
129 g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
134 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
138 g_warning ("Failed to acquire %s: %s",
139 NAME_TO_CLAIM, error->message);
140 g_error_free (error);
144 g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
149 dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",
150 G_TYPE_STRING, G_TYPE_INVALID);
151 dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",
152 G_CALLBACK (on_name_lost), NULL, NULL);
154 /* further setup ... */
156 </programlisting></informalexample>
159 While you can do things this way with GDBus too, using
160 g_dbus_proxy_call_sync(), it is much nicer to use the high-level API
162 <informalexample><programlisting><![CDATA[
164 on_name_acquired (GDBusConnection *connection,
168 /* further setup ... */
173 owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
175 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
182 g_main_loop_run (loop);
184 g_bus_unown_name (owner_id);
186 </programlisting></informalexample>
187 Note that g_bus_own_name() works asynchronously and requires
188 you to enter your mainloop to await the on_name_aquired()
189 callback. Also note that in order to avoid race conditions (e.g.
190 when your service is activated by a method call), you have to export
191 your manager object <emphasis>before</emphasis> acquiring the
192 name. The on_bus_acquired() callback is the right place to do
198 <title>Creating proxies for well-known names</title>
200 dbus-glib lets you create proxy objects for well-known names, like the
202 <informalexample><programlisting><![CDATA[
203 proxy = dbus_g_proxy_new_for_name (system_bus_connection,
204 "org.freedesktop.Accounts",
205 "/org/freedesktop/Accounts",
206 "org.freedesktop.Accounts");
208 </programlisting></informalexample>
209 For a #DBusGProxy constructed like this, method calls will be sent to
210 the current owner of the name, and that owner can change over time.
213 The same can be achieved with #GDBusProxy:
214 <informalexample><programlisting><![CDATA[
216 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
217 G_DBUS_PROXY_FLAGS_NONE,
218 NULL, /* GDBusInterfaceInfo */
219 "org.freedesktop.Accounts",
220 "/org/freedesktop/Accounts",
221 "org.freedesktop.Accounts",
222 NULL, /* GCancellable */
225 </programlisting></informalexample>
226 For an added layer of safety, you can specify what D-Bus
227 interface the proxy is expected to conform to by using the
228 #GDBusInterfaceInfo type. Additionally, #GDBusProxy loads,
229 caches and tracks changes to the D-Bus properties on the remote
230 object. It also sets up match rules so D-Bus signals from the
231 remote object are delivered locally.
234 The #GDBusProxy type normally isn't used directly - instead
235 proxies subclassing #GDBusProxy generated by <command><link
236 linkend="gdbus-codegen">gdbus-codegen</link></command> is used, see <xref linkend="gdbus-example-gdbus-codegen"/>
241 <title>Generating code and docs</title>
243 <section id="gdbus-example-gdbus-codegen">
244 <title>Using gdbus-codegen</title>
247 dbus-glib comes with <command>dbus-binding-tool</command>, which
248 can produce somewhat nice client- and server-side wrappers for a D-Bus interface.
249 With GDBus, <command><link
250 linkend="gdbus-codegen">gdbus-codegen</link></command> is used and like
251 its counterpart, it also takes D-Bus Introspection XML as input:
253 <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="../../../../gio/tests/gdbus-object-manager-example/gdbus-example-objectmanager.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
255 If this XML is processed like this
256 <informalexample><programlisting><![CDATA[
257 gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
258 --generate-c-code generated-code \
259 --c-namespace Example \
260 --c-generate-object-manager \
261 --generate-docbook generated-docs \
262 gdbus-example-objectmanager.xml
263 ]]></programlisting></informalexample>
264 then two files <filename>generated-code.h</filename> and
265 <filename>generated-code.c</filename> are
266 generated. Additionally, two XML files
267 <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal</filename> and
268 <filename>generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat</filename>
269 with Docbook XML are generated. For an example of what the docs look
271 linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal">the Animal D-Bus interface documentation</link>.
274 linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat">the Cat D-Bus interface documentation</link>.
277 While the contents of <filename>generated-code.h</filename> and
278 <filename>generated-code.c</filename> are best described by the
280 linkend="gdbus-codegen">gdbus-codegen</link></command> manual
281 page, brief examples of how this generated code can be used can be found in
282 <xref linkend="gdbus-example-codegen-server"/>
284 linkend="gdbus-example-codegen-client"/>. Additionally, since
285 the generated code has 100% gtk-doc coverage, see
286 #ExampleAnimal, #ExampleCat, #ExampleObject and
287 #ExampleObjectManagerClient pages for documentation.
290 <example id="gdbus-example-codegen-server"><title>Server-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-objectmanager-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
292 <example id="gdbus-example-codegen-client"><title>Client-side application using generated code</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-objectmanager-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
296 <xi:include href="../../../../gio/tests/gdbus-object-manager-example/gdbus-example-objectmanager-generated-org.gtk.GDBus.Example.ObjectManager.Animal.xml"/>
297 <xi:include href="../../../../gio/tests/gdbus-object-manager-example/gdbus-example-objectmanager-generated-org.gtk.GDBus.Example.ObjectManager.Cat.xml"/>
298 <xi:include href="../gdbus-object-manager-example/xml/ExampleAnimal.xml"/>
299 <xi:include href="../gdbus-object-manager-example/xml/ExampleCat.xml"/>
300 <xi:include href="../gdbus-object-manager-example/xml/ExampleObject.xml"/>
301 <xi:include href="../gdbus-object-manager-example/xml/ExampleObjectManagerClient.xml"/>