</sect1>
<sect1 id="glib-client">
- <title>GLib API: Using Remote Objects</title>
-
- <para>
- The GLib binding is defined in the header file
- <literal><dbus/dbus-glib.h></literal>.
- </para>
-
- <sect2 id="glib-typemappings">
- <title>D-Bus - GLib type mappings</title>
- <para>
- The heart of the GLib bindings for D-Bus is the mapping it
- provides between D-Bus "type signatures" and GLib types
- (<literal>GType</literal>). The D-Bus type system is composed of
- a number of "basic" types, along with several "container" types.
- </para>
- <sect3 id="glib-basic-typemappings">
- <title>Basic type mappings</title>
- <para>
- Below is a list of the basic types, along with their associated
- mapping to a <literal>GType</literal>.
- <informaltable>
- <tgroup cols="4">
- <thead>
- <row>
- <entry>D-Bus basic type</entry>
- <entry>GType</entry>
- <entry>Free function</entry>
- <entry>Notes</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>BYTE</literal></entry>
- <entry><literal>G_TYPE_UCHAR</literal></entry>
- <entry></entry>
- <entry></entry>
- </row><row>
- <entry><literal>BOOLEAN</literal></entry>
- <entry><literal>G_TYPE_BOOLEAN</literal></entry>
- <entry></entry>
- <entry></entry>
- </row><row>
- <entry><literal>INT16</literal></entry>
- <entry><literal>G_TYPE_INT</literal></entry>
- <entry></entry>
- <entry>Will be changed to a <literal>G_TYPE_INT16</literal> once GLib has it</entry>
- </row><row>
- <entry><literal>UINT16</literal></entry>
- <entry><literal>G_TYPE_UINT</literal></entry>
- <entry></entry>
- <entry>Will be changed to a <literal>G_TYPE_UINT16</literal> once GLib has it</entry>
- </row><row>
- <entry><literal>INT32</literal></entry>
- <entry><literal>G_TYPE_INT</literal></entry>
- <entry></entry>
- <entry>Will be changed to a <literal>G_TYPE_INT32</literal> once GLib has it</entry>
- </row><row>
- <entry><literal>UINT32</literal></entry>
- <entry><literal>G_TYPE_UINT</literal></entry>
- <entry></entry>
- <entry>Will be changed to a <literal>G_TYPE_UINT32</literal> once GLib has it</entry>
- </row><row>
- <entry><literal>INT64</literal></entry>
- <entry><literal>G_TYPE_GINT64</literal></entry>
- <entry></entry>
- <entry></entry>
- </row><row>
- <entry><literal>UINT64</literal></entry>
- <entry><literal>G_TYPE_GUINT64</literal></entry>
- <entry></entry>
- <entry></entry>
- </row><row>
- <entry><literal>DOUBLE</literal></entry>
- <entry><literal>G_TYPE_DOUBLE</literal></entry>
- <entry></entry>
- <entry></entry>
- </row><row>
- <entry><literal>STRING</literal></entry>
- <entry><literal>G_TYPE_STRING</literal></entry>
- <entry><literal>g_free</literal></entry>
- <entry></entry>
- </row><row>
- <entry><literal>OBJECT_PATH</literal></entry>
- <entry><literal>DBUS_TYPE_G_PROXY</literal></entry>
- <entry><literal>g_object_unref</literal></entry>
- <entry>The returned proxy does not have an interface set; use <literal>dbus_g_proxy_set_interface</literal> to invoke methods</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- As you can see, the basic mapping is fairly straightforward.
- </para>
- </sect3>
- <sect3 id="glib-container-typemappings">
- <title>Container type mappings</title>
- <para>
- The D-Bus type system also has a number of "container"
- types, such as <literal>DBUS_TYPE_ARRAY</literal> and
- <literal>DBUS_TYPE_STRUCT</literal>. The D-Bus type system
- is fully recursive, so one can for example have an array of
- array of strings (i.e. type signature
- <literal>aas</literal>).
- </para>
- <para>
- However, not all of these types are in common use; for
- example, at the time of this writing the author knows of no
- one using <literal>DBUS_TYPE_STRUCT</literal>, or a
- <literal>DBUS_TYPE_ARRAY</literal> containing any non-basic
- type. The approach the GLib bindings take is pragmatic; try
- to map the most common types in the most obvious way, and
- let using less common and more complex types be less
- "natural".
- </para>
- <para>
- First, D-Bus type signatures which have an "obvious"
- corresponding built-in GLib type are mapped using that type:
- <informaltable>
- <tgroup cols="6">
- <thead>
- <row>
- <entry>D-Bus type signature</entry>
- <entry>Description</entry>
- <entry>GType</entry>
- <entry>C typedef</entry>
- <entry>Free function</entry>
- <entry>Notes</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>as</literal></entry>
- <entry>Array of strings</entry>
- <entry><literal>G_TYPE_STRV</literal></entry>
- <entry><literal>char **</literal></entry>
- <entry><literal>g_strfreev</literal></entry>
- <entry></entry>
- </row><row>
- <entry><literal>v</literal></entry>
- <entry>Generic value container</entry>
- <entry><literal>G_TYPE_VALUE</literal></entry>
- <entry><literal>GValue *</literal></entry>
- <entry><literal>g_value_unset</literal></entry>
- <entry>The calling conventions for values expect that method callers have allocated return values; see below.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- <para>
- The next most common recursive type signatures are arrays of
- basic values. The most obvious mapping for arrays of basic
- types is a <literal>GArray</literal>. Now, GLib does not
- provide a builtin <literal>GType</literal> for
- <literal>GArray</literal>. However, we actually need more than
- that - we need a "parameterized" type which includes the
- contained type. Why we need this we will see below.
- </para>
- <para>
- The approach taken is to create these types in the D-Bus GLib
- bindings; however, there is nothing D-Bus specific about them.
- In the future, we hope to include such "fundamental" types in GLib
- itself.
- <informaltable>
- <tgroup cols="6">
- <thead>
- <row>
- <entry>D-Bus type signature</entry>
- <entry>Description</entry>
- <entry>GType</entry>
- <entry>C typedef</entry>
- <entry>Free function</entry>
- <entry>Notes</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>ay</literal></entry>
- <entry>Array of bytes</entry>
- <entry><literal>DBUS_TYPE_G_UCHAR_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>au</literal></entry>
- <entry>Array of uint</entry>
- <entry><literal>DBUS_TYPE_G_UINT_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>ai</literal></entry>
- <entry>Array of int</entry>
- <entry><literal>DBUS_TYPE_G_INT_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>ax</literal></entry>
- <entry>Array of int64</entry>
- <entry><literal>DBUS_TYPE_G_INT64_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>at</literal></entry>
- <entry>Array of uint64</entry>
- <entry><literal>DBUS_TYPE_G_UINT64_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>ad</literal></entry>
- <entry>Array of double</entry>
- <entry><literal>DBUS_TYPE_G_DOUBLE_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- <row>
- <entry><literal>ab</literal></entry>
- <entry>Array of boolean</entry>
- <entry><literal>DBUS_TYPE_G_BOOLEAN_ARRAY</literal></entry>
- <entry><literal>GArray *</literal></entry>
- <entry>g_array_free</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- <para>
- D-Bus also includes a special type DBUS_TYPE_DICT_ENTRY which
- is only valid in arrays. It's intended to be mapped to a "dictionary"
- type by bindings. The obvious GLib mapping here is GHashTable. Again,
- however, there is no builtin <literal>GType</literal> for a GHashTable.
- Moreover, just like for arrays, we need a parameterized type so that
- the bindings can communiate which types are contained in the hash table.
- </para>
- <para>
- At present, only strings are supported. Work is in progress to
- include more types.
- <informaltable>
- <tgroup cols="6">
- <thead>
- <row>
- <entry>D-Bus type signature</entry>
- <entry>Description</entry>
- <entry>GType</entry>
- <entry>C typedef</entry>
- <entry>Free function</entry>
- <entry>Notes</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>a{ss}</literal></entry>
- <entry>Dictionary mapping strings to strings</entry>
- <entry><literal>DBUS_TYPE_G_STRING_STRING_HASHTABLE</literal></entry>
- <entry><literal>GHashTable *</literal></entry>
- <entry>g_hash_table_destroy</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </sect3>
- <sect3 id="glib-generic-typemappings">
- <title>Arbitrarily recursive type mappings</title>
- <para>
- Finally, it is possible users will want to write or invoke D-Bus
- methods which have arbitrarily complex type signatures not
- directly supported by these bindings. For this case, we have a
- <literal>DBusGValue</literal> which acts as a kind of special
- variant value which may be iterated over manually. The
- <literal>GType</literal> associated is
- <literal>DBUS_TYPE_G_VALUE</literal>.
- </para>
- <para>
- TODO insert usage of <literal>DBUS_TYPE_G_VALUE</literal> here.
- </para>
- </sect3>
- </sect2>
- <sect2 id="sample-program-1">
- <title>A sample program</title>
- <para>Here is a D-Bus program using the GLib bindings.
-<programlisting>
-int
-main (int argc, char **argv)
-{
- DBusGConnection *connection;
- GError *error;
- DBusGProxy *proxy;
- char **name_list;
- char **name_list_ptr;
-
- g_type_init ();
-
- error = NULL;
- connection = dbus_g_bus_get (DBUS_BUS_SESSION,
- &error);
- if (connection == NULL)
- {
- g_printerr ("Failed to open connection to bus: %s\n",
- error->message);
- g_error_free (error);
- exit (1);
- }
-
- /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */
-
- proxy = dbus_g_proxy_new_for_name (connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- /* Call ListNames method, wait for reply */
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "ListNames", &error, G_TYPE_INVALID,
- G_TYPE_STRV, &name_list, G_TYPE_INVALID))
- {
- /* Just do demonstrate remote exceptions versus regular GError */
- if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
- g_printerr ("Caught remote method exception %s: %s",
- dbus_g_error_get_name (error),
- error->message);
- else
- g_printerr ("Error: %s\n", error->message);
- g_error_free (error);
- exit (1);
- }
-
- /* Print the results */
-
- g_print ("Names on the message bus:\n");
-
- for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++)
- {
- g_print (" %s\n", *name_list_ptr);
- }
- g_strfreev (name_list);
-
- g_object_unref (proxy);
-
- return 0;
-}
-</programlisting>
- </para>
- </sect2>
- <sect2 id="glib-program-setup">
- <title>Program initalization</title>
- <para>
- A connection to the bus is acquired using
- <literal>dbus_g_bus_get</literal>. Next, a proxy
- is created for the object "/org/freedesktop/DBus" with
- interface <literal>org.freedesktop.DBus</literal>
- on the service <literal>org.freedesktop.DBus</literal>.
- This is a proxy for the message bus itself.
- </para>
- </sect2>
- <sect2 id="glib-method-invocation">
- <title>Understanding method invocation</title>
- <para>
- You have a number of choices for method invocation. First, as
- used above, <literal>dbus_g_proxy_call</literal> sends a
- method call to the remote object, and blocks until a reply is
- recieved. The outgoing arguments are specified in the varargs
- array, terminated with <literal>G_TYPE_INVALID</literal>.
- Next, pointers to return values are specified, followed again
- by <literal>G_TYPE_INVALID</literal>.
- </para>
- <para>
- To invoke a method asynchronously, use
- <literal>dbus_g_proxy_begin_call</literal>. This returns a
- <literal>DBusGPendingCall</literal> object; you may then set a
- notification function using
- <literal>dbus_g_pending_call_set_notify</literal>.
- </para>
- </sect2>
- <sect2 id="glib-signal-connection">
- <title>Connecting to object signals</title>
- <para>
- You may connect to signals using
- <literal>dbus_g_proxy_add_signal</literal> and
- <literal>dbus_g_proxy_connect_signal</literal>. You must
- invoke <literal>dbus_g_proxy_add_signal</literal> to specify
- the signature of your signal handlers; you may then invoke
- <literal>dbus_g_proxy_connect_signal</literal> multiple times.
- </para>
- <para>
- Note that it will often be the case that there is no builtin
- marshaller for the type signature of a remote signal. In that
- case, you must generate a marshaller yourself by using
- <application>glib-genmarshal</application>, and then register
- it using <literal>dbus_g_object_register_marshaller</literal>.
- </para>
- </sect2>
- <sect2 id="glib-error-handling">
- <title>Error handling and remote exceptions</title>
- <para>
- All of the GLib binding methods such as
- <literal>dbus_g_proxy_end_call</literal> return a
- <literal>GError</literal>. This <literal>GError</literal> can
- represent two different things:
- <itemizedlist>
- <listitem>
- <para>
- An internal D-Bus error, such as an out-of-memory
- condition, an I/O error, or a network timeout. Errors
- generated by the D-Bus library itself have the domain
- <literal>DBUS_GERROR</literal>, and a corresponding code
- such as <literal>DBUS_GERROR_NO_MEMORY</literal>. It will
- not be typical for applications to handle these errors
- specifically.
- </para>
- </listitem>
- <listitem>
- <para>
- A remote D-Bus exception, thrown by the peer, bus, or
- service. D-Bus remote exceptions have both a textual
- "name" and a "message". The GLib bindings store this
- information in the <literal>GError</literal>, but some
- special rules apply.
- </para>
- <para>
- The set error will have the domain
- <literal>DBUS_GERROR</literal> as above, and will also
- have the code
- <literal>DBUS_GERROR_REMOTE_EXCEPTION</literal>. In order
- to access the remote exception name, you must use a
- special accessor, such as
- <literal>dbus_g_error_has_name</literal> or
- <literal>dbus_g_error_get_name</literal>. The remote
- exception detailed message is accessible via the regular
- GError <literal>message</literal> member.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect2>
- <sect2 id="glib-more-examples">
- <title>More examples of method invocation</title>
- <sect3 id="glib-sending-stuff">
- <title>Sending an integer and string, receiving an array of bytes</title>
- <para>
-<programlisting>
- GArray *arr;
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "Foobar", &error,
- G_TYPE_INT, 42, G_TYPE_STRING, "hello",
- G_TYPE_INVALID,
- DBUS_TYPE_G_UCHAR_ARRAY, &arr, G_TYPE_INVALID))
- {
- /* Handle error */
- }
- g_assert (arr != NULL);
- printf ("got back %u values", arr->len);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-sending-hash">
- <title>Sending a GHashTable</title>
- <para>
-<programlisting>
- GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
- guint32 ret;
-
- g_hash_table_insert (hash, "foo", "bar");
- g_hash_table_insert (hash, "baz", "whee");
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "HashSize", &error,
- DBUS_TYPE_G_STRING_STRING_HASH, hash, G_TYPE_INVALID,
- G_TYPE_UINT, &ret, G_TYPE_INVALID))
- {
- /* Handle error */
- }
- g_assert (ret == 2);
- g_hash_table_destroy (hash);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-receiving-bool-int">
- <title>Receiving a boolean and a string</title>
- <para>
-<programlisting>
- gboolean boolret;
- char *strret;
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "GetStuff", &error,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &boolret,
- G_TYPE_STRING, &strret,
- G_TYPE_INVALID))
- {
- /* Handle error */
- }
- printf ("%s %s", boolret ? "TRUE" : "FALSE", strret);
- g_free (strret);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-sending-str-arrays">
- <title>Sending two arrays of strings</title>
- <para>
-<programlisting>
- /* NULL terminate */
- char *strs_static[] = {"foo", "bar", "baz", NULL};
- /* Take pointer to array; cannot pass array directly */
- char **strs_static_p = strs_static;
- char **strs_dynamic;
-
- strs_dynamic = g_new (char *, 4);
- strs_dynamic[0] = g_strdup ("hello");
- strs_dynamic[1] = g_strdup ("world");
- strs_dynamic[2] = g_strdup ("!");
- /* NULL terminate */
- strs_dynamic[3] = NULL;
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "TwoStrArrays", &error,
- G_TYPE_STRV, strs_static_p,
- G_TYPE_STRV, strs_dynamic,
- G_TYPE_INVALID,
- G_TYPE_INVALID))
- {
- /* Handle error */
- }
- g_strfreev (strs_dynamic);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-getting-str-array">
- <title>Sending a boolean, receiving an array of strings</title>
- <para>
-<programlisting>
- char **strs;
- char **strs_p;
- gboolean blah;
-
- error = NULL;
- blah = TRUE;
- if (!dbus_g_proxy_call (proxy, "GetStrs", &error,
- G_TYPE_BOOLEAN, blah,
- G_TYPE_INVALID,
- G_TYPE_STRV, &strs,
- G_TYPE_INVALID))
- {
- /* Handle error */
- }
- for (strs_p = strs; *strs_p; strs_p++)
- printf ("got string: \"%s\"", *strs_p);
- g_strfreev (strs);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-sending-variant">
- <title>Sending a variant</title>
- <para>
-<programlisting>
- GValue val = {0, };
-
- g_value_init (&val, G_TYPE_STRING);
- g_value_set_string (&val, "hello world");
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "SendVariant", &error,
- G_TYPE_VALUE, &val, G_TYPE_INVALID,
- G_TYPE_INVALID))
- {
- /* Handle error */
- }
- g_assert (ret == 2);
- g_value_unset (&val);
-</programlisting>
- </para>
- </sect3>
- <sect3 id="glib-receiving-variant">
- <title>Receiving a variant</title>
- <para>
-<programlisting>
- GValue val = {0, };
-
- error = NULL;
- if (!dbus_g_proxy_call (proxy, "GetVariant", &error, G_TYPE_INVALID,
- G_TYPE_VALUE, &val, G_TYPE_INVALID))
- {
- /* Handle error */
- }
- if (G_VALUE_TYPE (&val) == G_TYPE_STRING)
- printf ("%s\n", g_value_get_string (&val));
- else if (G_VALUE_TYPE (&val) == G_TYPE_INT)
- printf ("%d\n", g_value_get_int (&val));
- else
- ...
- g_value_unset (&val);
-</programlisting>
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="glib-generated-bindings">
- <title>Generated Bindings</title>
- <para>
- By using the Introspection XML files, convenient client-side bindings
- can be automatically created to ease the use of a remote DBus object.
- </para>
- <para>
- Here is a sample XML file which describes an object that exposes
- one method, named <literal>ManyArgs</literal>.
- <programlisting>
-<?xml version="1.0" encoding="UTF-8" ?>
-<node name="/com/example/MyObject">
- <interface name="com.example.MyObject">
- <method name="ManyArgs">
- <arg type="u" name="x" direction="in" />
- <arg type="s" name="str" direction="in" />
- <arg type="d" name="trouble" direction="in" />
- <arg type="d" name="d_ret" direction="out" />
- <arg type="s" name="str_ret" direction="out" />
- </method>
- </interface>
-</node>
-</programlisting>
- </para>
- <para>
- Run <literal>dbus-binding-tool --mode=glib-client
- <replaceable>FILENAME</replaceable> >
- <replaceable>HEADER_NAME</replaceable></literal> to generate the header
- file. For example: <command>dbus-binding-tool --mode=glib-client
- my-object.xml > my-object-bindings.h</command>. This will generate
- inline functions with the following prototypes:
- <programlisting>
-/* This is a blocking call */
-gboolean
-com_example_MyObject_many_args (DBusGProxy *proxy, const guint IN_x,
- const char * IN_str, const gdouble IN_trouble,
- gdouble* OUT_d_ret, char ** OUT_str_ret,
- GError **error);
-
-/* This is a non-blocking call */
-DBusGProxyCall*
-com_example_MyObject_many_args_async (DBusGProxy *proxy, const guint IN_x,
- const char * IN_str, const gdouble IN_trouble,
- com_example_MyObject_many_args_reply callback,
- gpointer userdata);
-
-/* This is the typedef for the non-blocking callback */
-typedef void
-(*com_example_MyObject_many_args_reply)
-(DBusGProxy *proxy, gdouble OUT_d_ret, char * OUT_str_ret,
- GError *error, gpointer userdata);
-</programlisting>
- The first argument in all functions is a <literal>DBusGProxy
- *</literal>, which you should create with the usual
- <literal>dbus_g_proxy_new_*</literal> functions. Following that are the
- "in" arguments, and then either the "out" arguments and a
- <literal>GError *</literal> for the synchronous (blocking) function, or
- callback and user data arguments for the asynchronous (non-blocking)
- function. The callback in the asynchronous function passes the
- <literal>DBusGProxy *</literal>, the returned "out" arguments, an
- <literal>GError *</literal> which is set if there was an error otherwise
- <literal>NULL</literal>, and the user data.
- </para>
- <para>
- As with the server-side bindings support (see <xref
- linkend="glib-server"/>), the exact behaviour of the client-side
- bindings can be manipulated using "annotations". Currently the only
- annotation used by the client bindings is
- <literal>org.freedesktop.DBus.GLib.NoReply</literal>, which sets the
- flag indicating that the client isn't expecting a reply to the method
- call, so a reply shouldn't be sent. This is often used to speed up
- rapid method calls where there are no "out" arguments, and not knowing
- if the method succeeded is an acceptable compromise to half the traffic
- on the bus.
- </para>
- </sect2>
- </sect1>
-
- <sect1 id="glib-server">
- <title>GLib API: Implementing Objects</title>
+ <title>GLib APIs</title>
<para>
- At the moment, to expose a GObject via D-Bus, you must
- write XML by hand which describes the methods exported
- by the object. In the future, this manual step will
- be obviated by the upcoming GLib introspection support.
+ The recommended GLib API for D-Bus is GDBus, which has been
+ distributed with GLib since version 2.26. It is not documented here.
+ See <ulink url="https://developer.gnome.org/gio/stable/gdbus-convenience.html">the
+ GLib documentation</ulink> for details of how to use GDBus.
</para>
- <para>
- Here is a sample XML file which describes an object that exposes
- one method, named <literal>ManyArgs</literal>.
-<programlisting>
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/com/example/MyObject">
- <interface name="com.example.MyObject">
- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object"/>
- <method name="ManyArgs">
- <!-- This is optional, and in this case is redunundant -->
- <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_many_args"/>
- <arg type="u" name="x" direction="in" />
- <arg type="s" name="str" direction="in" />
- <arg type="d" name="trouble" direction="in" />
- <arg type="d" name="d_ret" direction="out" />
- <arg type="s" name="str_ret" direction="out" />
- </method>
- </interface>
-</node>
-</programlisting>
- </para>
<para>
- This XML is in the same format as the D-Bus introspection XML
- format. Except we must include an "annotation" which give the C
- symbols corresponding to the object implementation prefix
- (<literal>my_object</literal>). In addition, if particular
- methods symbol names deviate from C convention
- (i.e. <literal>ManyArgs</literal> ->
- <literal>many_args</literal>), you may specify an annotation
- giving the C symbol.
+ An older API, dbus-glib, also exists. It is deprecated and should
+ not be used in new code. Whenever possible, porting existing code
+ from dbus-glib to GDBus is also recommended.
</para>
- <para>
- Once you have written this XML, run <literal>dbus-binding-tool --mode=glib-server <replaceable>FILENAME</replaceable> > <replaceable>HEADER_NAME</replaceable>.</literal> to
- generate a header file. For example: <command>dbus-binding-tool --mode=glib-server my-object.xml > my-object-glue.h</command>.
- </para>
- <para>
- Next, include the generated header in your program, and invoke
- <literal>dbus_g_object_class_install_info</literal> in the class
- initializer, passing the object class and "object info" included in the
- header. For example:
- <programlisting>
- dbus_g_object_type_install_info (COM_FOO_TYPE_MY_OBJECT, &com_foo_my_object_info);
- </programlisting>
- This should be done exactly once per object class.
- </para>
- <para>
- To actually implement the method, just define a C function named e.g.
- <literal>my_object_many_args</literal> in the same file as the info
- header is included. At the moment, it is required that this function
- conform to the following rules:
- <itemizedlist>
- <listitem>
- <para>
- The function must return a value of type <literal>gboolean</literal>;
- <literal>TRUE</literal> on success, and <literal>FALSE</literal>
- otherwise.
- </para>
- </listitem>
- <listitem>
- <para>
- The first parameter is a pointer to an instance of the object.
- </para>
- </listitem>
- <listitem>
- <para>
- Following the object instance pointer are the method
- input values.
- </para>
- </listitem>
- <listitem>
- <para>
- Following the input values are pointers to return values.
- </para>
- </listitem>
- <listitem>
- <para>
- The final parameter must be a <literal>GError **</literal>.
- If the function returns <literal>FALSE</literal> for an
- error, the error parameter must be initalized with
- <literal>g_set_error</literal>.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Finally, you can export an object using <literal>dbus_g_connection_register_g_object</literal>. For example:
- <programlisting>
- dbus_g_connection_register_g_object (connection,
- "/com/foo/MyObject",
- obj);
- </programlisting>
- </para>
-
- <sect2 id="glib-annotations">
- <title>Server-side Annotations</title>
- <para>
- There are several annotations that are used when generating the
- server-side bindings. The most common annotation is
- <literal>org.freedesktop.DBus.GLib.CSymbol</literal> but there are other
- annotations which are often useful.
- <variablelist>
- <varlistentry>
- <term><literal>org.freedesktop.DBus.GLib.CSymbol</literal></term>
- <listitem>
- <para>
- This annotation is used to specify the C symbol names for
- the various types (interface, method, etc), if it differs from the
- name DBus generates.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>org.freedesktop.DBus.GLib.Async</literal></term>
- <listitem>
- <para>
- This annotation marks the method implementation as an
- asynchronous function, which doesn't return a response straight
- away but will send the response at some later point to complete
- the call. This is used to implement non-blocking services where
- method calls can take time.
- </para>
- <para>
- When a method is asynchronous, the function prototype is
- different. It is required that the function conform to the
- following rules:
- <itemizedlist>
- <listitem>
- <para>
- The function must return a value of type <literal>gboolean</literal>;
- <literal>TRUE</literal> on success, and <literal>FALSE</literal>
- otherwise. TODO: the return value is currently ignored.
- </para>
- </listitem>
- <listitem>
- <para>
- The first parameter is a pointer to an instance of the object.
- </para>
- </listitem>
- <listitem>
- <para>
- Following the object instance pointer are the method
- input values.
- </para>
- </listitem>
- <listitem>
- <para>
- The final parameter must be a
- <literal>DBusGMethodInvocation *</literal>. This is used
- when sending the response message back to the client, by
- calling <literal>dbus_g_method_return</literal> or
- <literal>dbus_g_method_return_error</literal>.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>org.freedesktop.DBus.GLib.Const</literal></term>
- <listitem>
- <para>This attribute can only be applied to "out"
- <literal><arg></literal> nodes, and specifies that the
- parameter isn't being copied when returned. For example, this
- turns a 's' argument from a <literal>char **</literal> to a
- <literal>const char **</literal>, and results in the argument not
- being freed by DBus after the message is sent.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><literal>org.freedesktop.DBus.GLib.ReturnVal</literal></term>
- <listitem>
- <para>
- This attribute can only be applied to "out"
- <literal><arg></literal> nodes, and alters the expected
- function signature. It currently can be set to two values:
- <literal>""</literal> or <literal>"error"</literal>. The
- argument marked with this attribute is not returned via a
- pointer argument, but by the function's return value. If the
- attribute's value is the empty string, the <literal>GError
- *</literal> argument is also omitted so there is no standard way
- to return an error value. This is very useful for interfacing
- with existing code, as it is possible to match existing APIs.
- If the attribute's value is <literal>"error"</literal>, then the
- final argument is a <literal>GError *</literal> as usual.
- </para>
- <para>
- Some examples to demonstrate the usage. This introspection XML:
- <programlisting>
-<method name="Increment">
- <arg type="u" name="x" />
- <arg type="u" direction="out" />
-</method>
- </programlisting>
- Expects the following function declaration:
- <programlisting>
-gboolean
-my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error);
- </programlisting>
- </para>
- <para>
- This introspection XML:
- <programlisting>
-<method name="IncrementRetval">
- <arg type="u" name="x" />
- <arg type="u" direction="out" >
- <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/>
- </arg>
-</method>
- </programlisting>
- Expects the following function declaration:
- <programlisting>
-gint32
-my_object_increment_retval (MyObject *obj, gint32 x)
- </programlisting>
- </para>
- <para>
- This introspection XML:
- <programlisting>
-<method name="IncrementRetvalError">
- <arg type="u" name="x" />
- <arg type="u" direction="out" >
- <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/>
- </arg>
-</method>
- </programlisting>
- Expects the following function declaration:
- <programlisting>
-gint32
-my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
- </programlisting>
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
- </sect2>
</sect1>
<sect1 id="python-client">
</sect1>
<sect1 id="qt-client">
- <title>Qt API: Using Remote Objects</title>
- <para>
-
- The Qt bindings are not yet documented.
-
- </para>
- </sect1>
-
- <sect1 id="qt-server">
- <title>Qt API: Implementing Objects</title>
+ <title>Qt API</title>
<para>
- The Qt bindings are not yet documented.
+ The Qt binding for libdbus, QtDBus, has been distributed with Qt
+ since version 4.2. It is not documented here. See
+ <ulink url="http://qt-project.org/doc/qt-5/qtdbus-index.html">the Qt
+ documentation</ulink> for details of how to use QtDBus.
</para>
</sect1>
</article>