dbus/doc dbus-tutorial.xml,1.10,1.11 TODO,1.77,1.78
Colin Walters
walters at freedesktop.org
Sun Jun 12 20:01:28 PDT 2005
- Previous message: dbus/glib dbus-gvalue.h, 1.4, 1.5 dbus-gvalue.c, 1.8,
1.9 dbus-gvalue-utils.h, NONE, 1.1 dbus-gvalue-utils.c, NONE,
1.1 dbus-gtype-specialized.h, NONE,
1.1 dbus-gtype-specialized.c, NONE, 1.1 dbus-gproxy.c, 1.24,
1.25 dbus-gobject.h, 1.2, 1.3 dbus-gobject.c, 1.22,
1.23 dbus-gmain.c, 1.41, 1.42 dbus-binding-tool-glib.h, 1.4,
1.5 dbus-binding-tool-glib.c, 1.8, 1.9 Makefile.am, 1.17, 1.18
- Next message: dbus/dbus dbus-glib.h,1.9,1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvs/dbus/dbus/doc
In directory gabe:/tmp/cvs-serv11651/doc
Modified Files:
dbus-tutorial.xml TODO
Log Message:
2005-06-12 Colin Walters <walters at verbum.org>
Async signals and various bugfixes and testing by
Ross Burton <ross at burtonini.com>.
* glib/dbus-gvalue.h: (struct DBusBasicGValue): Delete.
(dbus_gvalue_genmarshal_name_from_type)
(dbus_gvalue_ctype_from_type): Moved to dbus-binding-tool-glib.c.
(dbus_gtype_to_dbus_type): Renamed to dbus_gtype_from_signature.
(dbus_g_value_types_init, dbus_gtype_from_signature)
(dbus_gtype_from_signature_iter, dbus_gtype_to_signature)
(dbus_gtypes_from_arg_signature): New function prototypes.
(dbus_gvalue_demarshal): Take context and error arguments.
(dbus_gvalue_demarshal_variant): New function.
(dbus_gvalue_demarshal_message): New function.
(dbus_gvalue_store): Delete.
* glib/dbus-gvalue.c:
File has been almost entirely rewritten; now we special-case
more types such as DBUS_TYPE_SIGNATURE, handle arrays and
hash tables correctly, etc. Full support for recursive values
is not yet complete.
* glib/dbus-gproxy.c (dbus_g_proxy_class_init): Change last
argument of signal to G_TYPE_POINTER since we now pass a
structure.
(lookup_g_marshaller): Delete in favor of
_dbus_gobject_lookup_marshaller.
(marshal_dbus_message_to_g_marshaller): Use
_dbus_gobject_lookup_marshaller and dbus_gvalue_demarshal_message
to handle remote signal callbacks.
(dbus_g_proxy_new_from_proxy): New function; creates a new
DBusGProxy by copying an existing one.
(dbus_g_proxy_get_interface, dbus_g_proxy_set_interface)
(dbus_g_proxy_get_path): New functions.
(dbus_g_proxy_marshal_args_to_message): New function;
factored out of existing code.
(DBUS_G_VALUE_ARRAY_COLLECT_ALL): Collect all arguments
from a varargs array.
(dbus_g_proxy_begin_call_internal): New function.
(dbus_g_proxy_end_call_internal): New function.
(dbus_g_proxy_begin_call): Take GTypes instead of DBus types
as arguments; simply invoke dbus_g_proxy_begin_call_internal
after collecting args into value array.
(dbus_g_proxy_end_call): Take GTypes instead of DBus types;
invoke dbus_g_proxy_end_call_internal.
(dbus_g_proxy_invoke): Simply invoke begin_call_interanl and
end_call_internal.
(dbus_g_proxy_call_no_reply): Take GTypes instead of DBus
types.
(array_free_all): New function.
(dbus_g_proxy_add_signal): Take GTypes.
* glib/dbus-gobject.h:
(_dbus_glib_marshal_dbus_message_to_gvalue_array): Delete.
(_dbus_gobject_get_path, _dbus_gobject_lookup_marshaller):
Prototype.
* glib/dbus-gobject.c: Add a global marshal_table hash which
stores mappings from type signatures to marshallers. Change lots
of invocations of dbus_gtype_to_dbus_type to
dbus_gtype_to_signature.
(_dbus_glib_marshal_dbus_message_to_gvalue_array): Delete.
(introspect_signals): Fix test for query.return_type.
(set_object_property): Update invocation of dbus_gvalue_demarshal.
(invoke_object_method): Many changes. Handle asynchronous
invocations. Convert arguments with
dbus_gvalue_demarshal_message. Handle errors. Use
DBusSignatureIter instead of strlen on args. Handle all arguments
generically. Special-case variants.
(dbus_g_method_return, dbus_g_method_return_error): New function.
(DBusGSignalClosure): New structure, closes over signal
information.
(dbus_g_signal_closure_new): New function.
(dbus_g_signal_closure_finalize): New function.
(signal_emitter_marshaller): New function; is special marshaller
which emits signals on bus.
(export_signals): New function; introspects object signals and
connects to them.
(dbus_g_object_type_install_info): Take GType instead of
GObjectClass.
(dbus_g_connection_register_g_object): Invoke export_signals.
(dbus_g_connection_lookup_g_object): New function.
(DBusGFuncSignature) New structure; used for mapping type
signatures to marshallers.
(funcsig_hash): New function; hashes DBusGFuncSignature.
(funcsig_equal): New function; compares DBusGFuncSignature.
(_dbus_gobject_lookup_marshaller): New function.
(dbus_g_object_register_marshaller): New function; used to
register a marshaller at runtime for a particular signature.
* glib/dbus-gmain.c (_dbus_gmain_test): Add various tests.
* glib/dbus-binding-tool-glib.h: Add DBUS_GLIB_ANNOTATION_ASYNC
which notes a server method implementation should be
asynchronous.
* glib/dbus-binding-tool-glib.c
(dbus_binding_tool_output_glib_server): Call
dbus_g_value_types_init.
(write_formal_parameters): Use dbus_gtype_from_signature. Handle
variants specially.
(dbus_g_type_get_lookup_function): Turn GType into an invocation
of a lookup function.
(write_args_for_direction): Use dbus_g_type_get_lookup_function.
(write_untyped_out_args): New method; write output arguments.
(write_formal_declarations_for_direction): Function for
writing prototypes.
(write_formal_parameters_for_direction): Function for
writing implementations.
(write_typed_args_for_direction): Function for writing
arguments prefixed with GTypes.
(write_async_method_client): Write out async version
of method.
* glib/dbus-binding-tool-glib.c: Include dbus-gvalue-utils.h.
(dbus_g_type_get_marshal_name): Move mapping from GType
to marshal name into here.
(dbus_g_type_get_c_name): Move into here.
(compute_marshaller): Convert signature to type with
dbus_gtype_from_signature, use dbus_g_type_get_marshal_name.
(compute_marshaller_name): Ditto.
(compute_marshaller): Handle async signal annotations.
(gather_marshallers): Return if we don't have a known
prefix.
(generate_glue): Collect introspection blob here, and
write all of the blob at the end. This allows an object
with multiple interfaces to work.
Mark async methods in introspection blob.
* glib/Makefile.am (libdbus_glib_1_la_SOURCES): Add
dbus-gtype-specialized.c, dbus-gtype-specialized.h,
dbus-gvalue-utils.h, dbus-gvalue-utils.c.
* dbus/dbus-glib.h: Don't include dbus-protocol.h; this
avoids people accidentally using DBUS_TYPE_* which should
not be necessary anymore.
Do include dbus-gtype-specialized.h, which are utilities
for GLib container types.
Add various #defines for types such as
DBUS_TYPE_G_BOOLEAN_ARRAY.
(DBusGValueIterator, DBusGValue): Define, not fully used
yet.
(dbus_g_value_get_g_type): Type for recursive value.
(dbus_g_value_open, dbus_g_value_iterator_get_value)
(dbus_g_value_iterator_get_values, dbus_g_value_iterator_recurse)
(dbus_g_value_free): Prototypes.
(dbus_g_object_register_marshaller, dbus_g_proxy_new_from_proxy): Prototype.
(dbus_g_proxy_set_interface): Prototype.
(dbus_g_proxy_begin_call, dbus_g_proxy_end_call)
(dbus_g_proxy_call_no_reply): Take GLib types instead of DBus
types.
(dbus_g_proxy_get_path, dbus_g_proxy_get_interface):
Accessors.
(DBusGAsyncData, DBusGMethodInvocation): Structures for
doing async invocations.
(dbus_g_method_return, dbus_g_method_return_error):
Prototypes.
* doc/dbus-tutorial.xml: Update GLib section.
* tools/dbus-viewer.c (load_child_nodes): Update
for new invocation type of dbus_g_proxy_end_call.
(load_from_service_thread_func): Ditto.
* tools/print-introspect.c (main): Ditto.
* tools/dbus-names-model.c (have_names_notify)
(names_model_reload, names_model_set_connection)
Use GTypes.
* python/Makefile.am (INCLUDES): Define DBUS_COMPILATION,
needed since Python bindings use GLib bindings.
* test/glib/Makefile.am (INCLUDES): Define DBUS_COMPILATION.
Add --prefix argument.
* tools/Makefile.am: Define DBUS_COMPILATION. Remove
unneeded --ignore-unsupported arg.
* test/glib/test-service-glib.c:
* test/glib/test-service-glib.xml:
* test/glib/test-dbus-glib.c: Add many more tests.
Index: dbus-tutorial.xml
===================================================================
RCS file: /cvs/dbus/dbus/doc/dbus-tutorial.xml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- dbus-tutorial.xml 23 Jan 2005 03:53:34 -0000 1.10
+++ dbus-tutorial.xml 13 Jun 2005 03:01:26 -0000 1.11
@@ -449,20 +449,294 @@
<title>GLib API: Using Remote Objects</title>
<para>
-
The GLib binding is defined in the header file
- <dbus/dbus-glib.h>. The API is very small, in sharp contrast to the
- low-level <dbus/dbus.h>.
-
- </para>
-
- <para>
- The GLib bindings are incomplete, see the TODO file and comments in the
- source code.
+ <dbus/dbus-glib.h>.
</para>
- <para>
-Here is a D-BUS program using the GLib bindings.
+ <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 G_TYPE_INT16 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>
+ </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>
+ </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>
+ </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>g_free</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>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 builtin 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>g_strfreev</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>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_BYTE_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)
@@ -470,10 +744,8 @@
DBusGConnection *connection;
GError *error;
DBusGProxy *proxy;
- DBusGPendingCall *call;
char **name_list;
- int name_list_len;
- int i;
+ char **name_list_ptr;
g_type_init ();
@@ -495,15 +767,10 @@
DBUS_PATH_ORG_FREEDESKTOP_DBUS,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS);
- /* Call ListNames method */
-
- call = dbus_g_proxy_begin_call (proxy, "ListNames", DBUS_TYPE_INVALID);
-
+ /* Call ListNames method, wait for reply */
error = NULL;
- if (!dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
- &name_list, &name_list_len,
- DBUS_TYPE_INVALID))
+ if (!dbus_g_proxy_invoke (proxy, "ListNames", &error, G_TYPE_INVALID,
+ G_TYPE_STRV, &name_list, G_TYPE_INVALID))
{
g_printerr ("Failed to complete ListNames call: %s\n",
error->message);
@@ -514,77 +781,348 @@
/* Print the results */
g_print ("Names on the message bus:\n");
- i = 0;
- while (i < name_list_len)
+
+ for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++)
{
- g_assert (name_list[i] != NULL);
- g_print (" %s\n", name_list[i]);
- ++i;
+ g_print (" %s\n", *name_list_ptr);
}
- g_assert (name_list[i] == NULL);
-
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_invoke</literal> sends a
+ 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
+ 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>. At the
+ moment, <literal>dbus_g_proxy_add_signal</literal> requires
+ the D-BUS types of the remote object; this will likely be
+ changed later.
+ </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_invoke (proxy, "Foobar", &error,
+ G_TYPE_INT, 42, G_TYPE_STRING, "hello",
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_UCHAR_ARRAY, &arr, G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete Foobar: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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");
- <para>
-
- DBusGProxy represents a remote object. dbus_g_proxy_begin_call() sends
- a method call to the remote object, and dbus_g_proxy_end_call() retrieves
- any return values or exceptions resulting from the method call.
- There are also DBusGProxy functions to connect and disconnect signals,
- not shown in the code example.
-
- </para>
-
- <para>
-
- dbus_g_bus_get() assumes that the application will use GMainLoop. The
- created connection will be associated with the main loop such that
- messages will be sent and received when the main loop runs. However, in
- the above code example the main loop never runs; D-BUS will not run the
- loop implicitly. Instead, dbus_g_proxy_end_call() will block until the
- method call has been sent and the reply received. A more complex GUI
- application might run the main loop while waiting for the method call
- reply. (DBusGPendingCall is currently missing the "notify me when the
- call is complete" functionality found in DBusPendingCall, but it should be
- added.)
+ error = NULL;
+ if (!dbus_g_proxy_invoke (proxy, "HashSize", &error,
+ DBUS_TYPE_G_STRING_STRING_HASH, hash, G_TYPE_INVALID,
+ G_TYPE_UINT, &ret, G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete HashSize: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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_invoke (proxy, "GetStuff", &error,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &boolret,
+ G_TYPE_STRING, &strret,
+ G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete GetStuff: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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;
- </para>
+ 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_invoke (proxy, "TwoStrArrays", &error,
+ G_TYPE_STRV, strs_static_p,
+ G_TYPE_STRV, strs_dynamic,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete TwoStrArrays: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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;
- <para>
-
- Future plans (see doc/TODO) are to use G_TYPE_STRING in place of
- DBUS_TYPE_STRING and so forth. In fact the above code is slightly
- incorrect at the moment, since it uses g_strfreev() to free a string array
- that was not allocated with g_malloc(). dbus_free_string_array() should
- really be used. However, once the GLib bindings are complete the returned
- data from dbus_g_proxy_end_call() will be allocated with g_malloc().
+ error = NULL;
+ blah = TRUE;
+ if (!dbus_g_proxy_invoke (proxy, "GetStrs", &error,
+ G_TYPE_BOOLEAN, blah,
+ G_TYPE_INVALID,
+ G_TYPE_STRV, &strs,
+ G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete GetStrs: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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, };
- </para>
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "hello world");
+
+ error = NULL;
+ if (!dbus_g_proxy_invoke (proxy, "SendVariant", &error,
+ G_TYPE_VALUE, &val, G_TYPE_INVALID,
+ G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete SendVariant: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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_invoke (proxy, "GetVariant", &error, G_TYPE_INVALID,
+ G_TYPE_VALUE, &val, G_TYPE_INVALID))
+ {
+ g_printerr ("Failed to complete GetVariant: %s\n",
+ error->message);
+ g_error_free (error);
+ exit (1);
+ }
+ 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>
</sect1>
<sect1 id="glib-server">
<title>GLib API: Implementing Objects</title>
-
<para>
-
- The GLib binding is defined in the header file
- <dbus/dbus-glib.h>. To implement an object, it's also necessary
- to use the dbus-glib-tool command line tool.
-
+ 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.
</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>
- The GLib bindings are incomplete. Implementing an object is not yet
- possible, see the TODO file and comments in the source code for details
- on what work needs doing.
+ 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.
+ </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-objet.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>, 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>
-
</sect1>
<sect1 id="qt-client">
Index: TODO
===================================================================
RCS file: /cvs/dbus/dbus/doc/TODO,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -d -r1.77 -r1.78
--- TODO 6 Jun 2005 18:55:22 -0000 1.77
+++ TODO 13 Jun 2005 03:01:26 -0000 1.78
@@ -39,12 +39,11 @@
Important for 1.0 GLib Bindings
===
- - finish dbus-glib-tool support for adding introspection
- data to GObject and autoexporting GObject using same
+ - Annotations for "do not take ownership of this return value" on server
- - Need to make sure that dbus-glib.h never returns any
- dbus_malloc() memory, only g_malloc().
- dbus_g_proxy_end_call() is the major offender.
+ - Fix signals
+
+ - Fix errors - need to get specific error back, not UnmappedError crap
- DBusGProxy doesn't emit "destroy" when it should
- Previous message: dbus/glib dbus-gvalue.h, 1.4, 1.5 dbus-gvalue.c, 1.8,
1.9 dbus-gvalue-utils.h, NONE, 1.1 dbus-gvalue-utils.c, NONE,
1.1 dbus-gtype-specialized.h, NONE,
1.1 dbus-gtype-specialized.c, NONE, 1.1 dbus-gproxy.c, 1.24,
1.25 dbus-gobject.h, 1.2, 1.3 dbus-gobject.c, 1.22,
1.23 dbus-gmain.c, 1.41, 1.42 dbus-binding-tool-glib.h, 1.4,
1.5 dbus-binding-tool-glib.c, 1.8, 1.9 Makefile.am, 1.17, 1.18
- Next message: dbus/dbus dbus-glib.h,1.9,1.10
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dbus-commit
mailing list