Add documentation on glib client bindings and annotations
authorRoss Burton <ross@openedhand.com>
Mon, 19 Dec 2005 18:11:05 +0000 (18:11 +0000)
committerRoss Burton <ross@openedhand.com>
Mon, 19 Dec 2005 18:11:05 +0000 (18:11 +0000)
ChangeLog
doc/dbus-tutorial.xml

index 34c2d4d..a09786d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-12-19  Ross Burton  <ross@openedhand.com>
+
+       * doc/dbus-tutorial.xml:
+       Document the Glib client-side bindings, and list all possible annotations.
+
 2005-12-19  John (J5) Palmieri  <johnp@redhat.com>
 
        * dbus/bus.c (dbus_bus_release_name): Add documentation
index a5b210b..78e8489 100644 (file)
@@ -15,9 +15,7 @@
        <surname>Pennington</surname>
        <affiliation>
          <orgname>Red Hat, Inc.</orgname>
-         <address>
-           <email>hp@pobox.com</email>
-         </address>
+         <address><email>hp@pobox.com</email></address>
        </affiliation>
       </author>
       <author>
@@ -29,9 +27,7 @@
        <surname>Palmieri</surname>
        <affiliation>
          <orgname>Red Hat, Inc.</orgname>
-         <address>
-           <email>johnp@redhat.com</email>
-         </address>
+         <address><email>johnp@redhat.com</email></address>
        </affiliation>
       </author>
       <author>
@@ -39,9 +35,7 @@
        <surname>Walters</surname>
        <affiliation>
          <orgname>Red Hat, Inc.</orgname>
-         <address>
-           <email>walters@redhat.com</email>
-         </address>
+         <address><email>walters@redhat.com</email></address>
        </affiliation>
       </author>
     </authorgroup>
 
     <para>
       The GLib binding is defined in the header file
-      &lt;dbus/dbus-glib.h&gt;.
+      <literal>&lt;dbus/dbus-glib.h&gt;</literal>.
     </para>
 
     <sect2 id="glib-typemappings">
                  <entry><literal>INT16</literal></entry>
                  <entry><literal>G_TYPE_INT</literal></entry>
                  <entry></entry>
-                 <entry>Will be changed to a G_TYPE_INT16 once GLib has it</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 G_TYPE_UINT16 once GLib has it</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 G_TYPE_INT32 once GLib has it</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 G_TYPE_UINT32 once GLib has it</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>
                  </row><row>
                  <entry><literal>STRING</literal></entry>
                  <entry><literal>G_TYPE_STRING</literal></entry>
-                 <entry>g_free</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>g_object_unref</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>
        </para>
        <para>
          First, D-BUS type signatures which have an "obvious"
-         corresponding builtin GLib type are mapped using that type:
+         corresponding built-in GLib type are mapped using that type:
          <informaltable>
            <tgroup cols="6">
              <thead>
                  <entry>Array of strings</entry>
                  <entry><literal>G_TYPE_STRV</literal></entry>
                  <entry><literal>char **</literal></entry>
-                 <entry>g_strfreev</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>g_value_unset</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>
@@ -836,7 +830,7 @@ main (int argc, char **argv)
       <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 reply is
+       method call to the remote object, and blocks until 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
@@ -1073,6 +1067,83 @@ main (int argc, char **argv)
        </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>
+&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
+&lt;node name="/com/example/MyObject"&gt;
+  &lt;interface name="com.example.MyObject"&gt;
+    &lt;method name="ManyArgs"&gt;
+      &lt;arg type="u" name="x" direction="in" /&gt;
+      &lt;arg type="s" name="str" direction="in" /&gt;
+      &lt;arg type="d" name="trouble" direction="in" /&gt;
+      &lt;arg type="d" name="d_ret" direction="out" /&gt;
+      &lt;arg type="s" name="str_ret" direction="out" /&gt;
+    &lt;/method&gt;
+  &lt;/interface&gt;
+&lt;/node&gt;
+</programlisting>
+      </para>
+      <para>
+        Run <literal>dbus-binding-tool --mode=glib-client
+          <replaceable>FILENAME</replaceable> &gt;
+          <replaceable>HEADER_NAME</replaceable></literal> to generate the header
+        file.  For example: <command>dbus-binding-tool --mode=glib-client
+          my-object.xml &gt; 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">
@@ -1118,13 +1189,13 @@ main (int argc, char **argv)
     </para>
     <para>
       Once you have written this XML, run <literal>dbus-binding-tool --mode=glib-server <replaceable>FILENAME</replaceable> &gt; <replaceable>HEADER_NAME</replaceable>.</literal> to
-      generate a header file.  For example: <command>dbus-binding-tool --mode=glib-server my-objet.xml &gt; my-object-glue.h</command>.
+      generate a header file.  For example: <command>dbus-binding-tool --mode=glib-server my-object.xml &gt; 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>, passing the
-      object class and "object info" included in the header.  For
-      example:
+      <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, &amp;com_foo_my_object_info);
       </programlisting>
@@ -1177,6 +1248,151 @@ main (int argc, char **argv)
                                                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>&lt;arg&gt;</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>&lt;arg&gt;</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>
+&lt;method name="Increment"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" /&gt;
+&lt;/method&gt;
+                </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>
+&lt;method name="IncrementRetval"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" &gt;
+    &lt;annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/&gt;
+  &lt;/arg&gt;
+&lt;/method&gt;
+                </programlisting>
+                Expects the following function declaration:
+                <programlisting>
+gint32
+my_object_increment_retval (MyObject *obj, gint32 x)
+                </programlisting>
+              </para>
+              <para>
+                This introspection XML:
+                <programlisting>
+&lt;method name="IncrementRetvalError"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" &gt;
+    &lt;annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/&gt;
+  &lt;/arg&gt;
+&lt;/method&gt;
+                </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">