Update German translation
[glib.git] / docs / reference / gio / migrating-gdbus.xml
blob5205a7cdbb0d0a01ba327d666f72107f23a59b51
1 <?xml version="1.0"?>
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">
6 ]>
7 <chapter>
8   <title>Migrating to GDBus</title>
10   <section>
11     <title>Conceptual differences</title>
13     <para>
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
17       differences:
18       <itemizedlist>
19         <listitem><para>
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.
28         </para></listitem>
29         <listitem><para>
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.
34         </para></listitem>
35         <listitem><para>
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).
41         </para></listitem>
42         <listitem><para>
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.
44         </para></listitem>
45         <listitem><para>
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.
52         </para></listitem>
53         <listitem><para>
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.
57         </para></listitem>
58         <listitem><para>
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.
62         </para></listitem>
63         <listitem><para>
64           GTestDBus provides API to create isolated unit tests <link
65           linkend="gio-D-Bus-Test-Scaffolding">GDBus Test Scaffolding</link>.
66         </para></listitem>
67       </itemizedlist>
68     </para>
69   </section>
71   <section>
72     <title>API comparison</title>
74     <table id="dbus-glib-vs-gdbus">
75       <title>dbus-glib APIs and their GDBus counterparts</title>
76       <tgroup cols="2">
77         <thead>
78            <row><entry>dbus-glib</entry><entry>GDBus</entry></row>
79         </thead>
80         <tbody>
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>
103         </tbody>
104       </tgroup>
105     </table>
106   </section>
108   <section>
109     <title>Owning bus names</title>
110     <para>
111       Using dbus-glib, you typically call RequestName manually
112       to own a name, like in the following excerpt:
113       <informalexample><programlisting><![CDATA[
114   error = NULL;
115   res = dbus_g_proxy_call (system_bus_proxy,
116                            "RequestName",
117                            &error,
118                            G_TYPE_STRING, NAME_TO_CLAIM,
119                            G_TYPE_UINT,   DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
120                            G_TYPE_INVALID,
121                            G_TYPE_UINT,   &result,
122                            G_TYPE_INVALID);
123   if (!res)
124     {
125       if (error != NULL)
126         {
127           g_warning ("Failed to acquire %s: %s",
128                      NAME_TO_CLAIM, error->message);
129           g_error_free (error);
130         }
131       else
132         {
133           g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
134         }
135       goto out;
136     }
138   if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
139     {
140       if (error != NULL)
141         {
142           g_warning ("Failed to acquire %s: %s",
143                      NAME_TO_CLAIM, error->message);
144           g_error_free (error);
145         }
146       else
147         {
148           g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
149         }
150       exit (1);
151     }
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>
161     </para>
162     <para>
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
165     for this:
166     <informalexample><programlisting><![CDATA[
167 static void
168 on_name_acquired (GDBusConnection *connection,
169                   const gchar     *name,
170                   gpointer         user_data)
172   /* further setup ... */
175 /* ... */
177   owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
178                              NAME_TO_CLAIM,
179                              G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
180                              on_bus_acquired,
181                              on_name_acquired,
182                              on_name_lost,
183                              NULL,
184                              NULL);
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
197     such preparations.
198     </para>
199   </section>
201   <section>
202     <title>Creating proxies for well-known names</title>
203     <para>
204       dbus-glib lets you create proxy objects for well-known names, like the
205       following example:
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");
211       ]]>
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.
215     </para>
216     <para>
217       The same can be achieved with #GDBusProxy:
218       <informalexample><programlisting><![CDATA[
219   error = NULL;
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 */
227                                          &error);
228       ]]>
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.
236     </para>
237     <para>
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"/>
241     </para>
242   </section>
244   <section id="gdbus-example-gdbus-codegen">
245     <title>Using gdbus-codegen</title>
247     <para>
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:
253     </para>
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>
255     <para>
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.
271     </para>
272     <para>
273       While the contents of <filename>generated-code.h</filename> and
274       <filename>generated-code.c</filename> are best described by the
275       <command><link
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"/>.
280     </para>
282   </section>
284 </chapter>