2023-10-09 23:22:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								Title: Migrating to GDBus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								SPDX-License-Identifier: LGPL-2.1-or-later
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								SPDX-FileCopyrightText: 2010 Matthias Clasen
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								SPDX-FileCopyrightText: 2010, 2011 David Zeuthen
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Migrating to GDBus
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Conceptual differences
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The central concepts of D-Bus are modelled in a very similar way in
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dbus-glib and GDBus. Both have objects representing connections, proxies and
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								method invocations. But there are some important differences:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  dbus-glib uses the libdbus reference implementation, GDBus doesn't. 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Instead, it relies on GIO streams as transport layer, and has its own
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  implementation for the D-Bus connection setup and authentication. Apart
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  from using streams as transport, avoiding libdbus also lets GDBus avoid
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  some thorny multithreading issues.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  dbus-glib uses the GObject type system for method arguments and return 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  values, including a homegrown container specialization mechanism. GDBus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  relies on the GVariant type system which is explicitly designed to match
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  D-Bus types.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  dbus-glib models only D-Bus interfaces and does not provide any types for 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  objects. GDBus models both D-Bus interfaces (via the GDBusInterface,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GDBusProxy and GDBusInterfaceSkeleton types) and objects (via the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GDBusObject, GDBusObjectSkeleton and GDBusObjectProxy types).
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  GDBus includes native support for the org.freedesktop.DBus.Properties (via 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  the GDBusProxy type) and org.freedesktop.DBus.ObjectManager D-Bus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  interfaces, dbus-glib doesn't.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  The typical way to export an object in dbus-glib involves generating glue 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  code from XML introspection data using dbus-binding-tool. GDBus provides a
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  similar tool called gdbus-codegen that can also generate Docbook D-Bus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  interface documentation.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  dbus-glib doesn't provide any convenience API for owning and watching bus 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  names, GDBus provides the `g_bus_own_name()`  and `g_bus_watch_name()` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  family of convenience functions.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  GDBus provides API to parse, generate and work with Introspection XML, 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  dbus-glib doesn't.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-  GTestDBus provides API to create isolated unit tests 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## API comparison
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| dbus-glib | GDBus |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								|-----------|-------|
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `DBusGConnection`  | `GDBusConnection`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `DBusGProxy`  | `GDBusProxy` , `GDBusInterface`  - also see `GDBusObjectProxy`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `DBusGObject`  | `GDBusInterfaceSkeleton` , `GDBusInterface`  - also see `GDBusObjectSkeleton`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `DBusGMethodInvocation`  | `GDBusMethodInvocation`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_bus_get()`  | `g_bus_get_sync()` , also see `g_bus_get()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_new_for_name()`  | `g_dbus_proxy_new_sync()`  and `g_dbus_proxy_new_for_bus_sync()` , also see `g_dbus_proxy_new()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_add_signal()`  | not needed, use the generic “g-signal” |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_connect_signal()`  | use `g_signal_connect()`  with “g-signal” |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_connection_register_g_object()`  | `g_dbus_connection_register_object()`  - also see `g_dbus_object_manager_server_export()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_connection_unregister_g_object()`  | `g_dbus_connection_unregister_object()`  - also see `g_dbus_object_manager_server_unexport()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_object_type_install_info()`  | introspection data is installed while registering an object, see `g_dbus_connection_register_object()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_begin_call()`  | `g_dbus_proxy_call()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_end_call()`  | `g_dbus_proxy_call_finish()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_proxy_call()`  | `g_dbus_proxy_call_sync()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_error_domain_register()`  | `g_dbus_error_register_error_domain()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_error_has_name()`  | no direct equivalent, see `g_dbus_error_get_remote_error()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_method_return()`  | `g_dbus_method_invocation_return_value()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_method_return_error()`  | `g_dbus_method_invocation_return_error()`  and variants |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `dbus_g_method_get_sender()`  | `g_dbus_method_invocation_get_sender()`  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Owning bus names
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Using dbus-glib, you typically call RequestName manually to own a name, like in the following excerpt:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								error = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								res = dbus_g_proxy_call (system_bus_proxy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         "RequestName",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         & error,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_STRING, NAME_TO_CLAIM,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_UINT,   DBUS_NAME_FLAG_ALLOW_REPLACEMENT,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_INVALID,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_UINT,   & result,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_INVALID);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if (!res)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if (error != NULL)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_warning ("Failed to acquire %s: %s",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   NAME_TO_CLAIM, error->message);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_error_free (error);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if (error != NULL)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_warning ("Failed to acquire %s: %s",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   NAME_TO_CLAIM, error->message);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_error_free (error);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    exit (1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dbus_g_proxy_add_signal (system_bus_proxy, "NameLost",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         G_TYPE_STRING, G_TYPE_INVALID);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dbus_g_proxy_connect_signal (system_bus_proxy, "NameLost",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             G_CALLBACK (on_name_lost), NULL, NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* further setup ... */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								While you can do things this way with GDBus too, using
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`g_dbus_proxy_call_sync()` , it is much nicer to use the high-level API for 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								this:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_name_acquired (GDBusConnection *connection,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  const gchar     *name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  gpointer         user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  /* further setup ... */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ... */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             NAME_TO_CLAIM,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             on_bus_acquired,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             on_name_acquired,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             on_name_lost,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             NULL,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_main_loop_run (loop);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_bus_unown_name (owner_id);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Note that `g_bus_own_name()`  works asynchronously and requires you to enter
							 
						 
					
						
							
								
									
										
										
										
											2024-04-01 10:54:59 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								your mainloop to await the `on_name_acquired()`  callback. Also note that in
							 
						 
					
						
							
								
									
										
										
										
											2023-10-09 23:22:20 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								order to avoid race conditions (e.g. when your service is activated by a
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								method call), you have to export your manager object before acquiring the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								name. The `on_bus_acquired()`  callback is the right place to do such
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								preparations.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Creating proxies for well-known names
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dbus-glib lets you create proxy objects for well-known names, like the following example:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								proxy = dbus_g_proxy_new_for_name (system_bus_connection,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   "org.freedesktop.Accounts",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   "/org/freedesktop/Accounts",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   "org.freedesktop.Accounts");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								For a DBusGProxy constructed like this, method calls will be sent to the current owner of the name, and that owner can change over time.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The same can be achieved with GDBusProxy:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								error = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       G_DBUS_PROXY_FLAGS_NONE,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       NULL, /* GDBusInterfaceInfo */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       "org.freedesktop.Accounts",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       "/org/freedesktop/Accounts",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       "org.freedesktop.Accounts",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       NULL, /* GCancellable */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       &error); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								For an added layer of safety, you can specify what D-Bus interface the proxy
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								is expected to conform to by using the GDBusInterfaceInfo type.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Additionally, GDBusProxy loads, caches and tracks changes to the D-Bus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								properties on the remote object. It also sets up match rules so D-Bus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								signals from the remote object are delivered locally.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The GDBusProxy type normally isn't used directly - instead proxies
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								subclassing GDBusProxy generated by `gdbus-codegen`  is used, see the section
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								called “Using gdbus-codegen”.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								## Generating code and docs
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								### Using gdbus-codegen
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								dbus-glib comes with dbus-binding-tool, which can produce somewhat nice
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								client- and server-side wrappers for a D-Bus interface. With GDBus,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gdbus-codegen is used and like its counterpart, it also takes D-Bus
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Introspection XML as input:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#### Example D-Bus Introspection XML
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```xml
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< node >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  <!--  org.gtk.GDBus.Example.ObjectManager.Animal:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       @short_description:  Example docs generated by gdbus-codegen
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       @since:  2.30
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       This D-Bus interface is used to describe a simple animal.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  < interface  name = "org.gtk.GDBus.Example.ObjectManager.Animal" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    <!--  Mood: The mood of the animal.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         @since:  2.30
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         Known values for this property include
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         < literal > Happy< / literal >  and < literal > Sad< / literal > . Use the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         org.gtk.GDBus.Example.ObjectManager.Animal.Poke() method to
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         change this property.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         This property influences how often the animal jumps up and
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         down, see the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         #org .gtk.GDBus.Example.ObjectManager.Animal::Jumped signal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         for more details.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < property  name = "Mood"  type = "s"  access = "read" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    <!-- 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Poke:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @make_sad:  Whether to make the animal sad.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @make_happy:  Whether to make the animal happy.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @since:  2.30
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Method used to changing the mood of the animal. See also the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #org .gtk.GDBus.Example.ObjectManager.Animal:Mood property.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < method  name = "Poke" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      < arg  direction = "in"  type = "b"  name = "make_sad" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      < arg  direction = "in"  type = "b"  name = "make_happy" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < / method > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    <!-- 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Jumped:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @height:  Height, in meters, that the animal jumped.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @since:  2.30
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Emitted when the animal decides to jump.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < signal  name = "Jumped" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      < arg  type = "d"  name = "height" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < / signal > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    <!-- 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Foo:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Property with no < quote > since< / quote >  annotation (should inherit the 2.30 from its containing interface).
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < property  name = "Foo"  type = "s"  access = "read" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    <!-- 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Bar:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        @since:  2.36
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Property with a later < quote > since< / quote >  annotation.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    < property  name = "Bar"  type = "s"  access = "read" / > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  < / interface > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  <!--  org.gtk.GDBus.Example.ObjectManager.Cat:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       @short_description:  More example docs generated by gdbus-codegen
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       This D-Bus interface is used to describe a cat. Right now there
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       are no properties, methods or signals associated with this
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       interface so it is essentially a < ulink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       url="http://en.wikipedia.org/wiki/Marker_interface_pattern">Marker
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       Interface< / ulink > .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       Note that D-Bus objects implementing this interface also
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       implement the #org .gtk.GDBus.Example.ObjectManager.Animal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       interface.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -->
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  < interface  name = "org.gtk.GDBus.Example.ObjectManager.Cat" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  < / interface > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								< / node >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								If this XML is processed like this
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              --generate-c-code generated-code	                      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              --c-namespace Example 				      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              --c-generate-object-manager			      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              --generate-docbook generated-docs                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              gdbus-example-objectmanager.xml
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								then two files generated-code.h and generated-code.c are generated.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Additionally, two XML files
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								generated-docs-org.gtk.GDBus.Example.ObjectManager.Animal and
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								generated-docs-org.gtk.GDBus.Example.ObjectManager.Cat with Docbook XML are
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								generated.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								While the contents of `generated-code.h`  and `generated-code.c`  are best described by the `gdbus-codegen`  manual page, here's a brief example of how this generated code can be used:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#include "gdbus-object-manager-example/objectmanager-gen.h"
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ---------------------------------------------------------------------------------------------------- */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static GDBusObjectManagerServer *manager = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static gboolean
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_animal_poke (ExampleAnimal          *animal,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                GDBusMethodInvocation  *invocation,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                gboolean                make_sad,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                gboolean                make_happy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                gpointer                user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if ((make_sad & &  make_happy) || (!make_sad & &  !make_happy))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_dbus_method_invocation_return_dbus_error (invocation,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                  "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                  "Exactly one of make_sad or make_happy must be TRUE");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (make_sad)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          g_dbus_method_invocation_return_dbus_error (invocation,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                      "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                      "Sad animal is already sad");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_animal_set_mood (animal, "Sad");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_animal_complete_poke (animal, invocation);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (make_happy)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          g_dbus_method_invocation_return_dbus_error (invocation,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                      "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                      "Happy animal is already happy");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_animal_set_mood (animal, "Happy");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_animal_complete_poke (animal, invocation);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_assert_not_reached ();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 out:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return G_DBUS_METHOD_INVOCATION_HANDLED;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_bus_acquired (GDBusConnection *connection,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 const gchar     *name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 gpointer         user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ExampleObjectSkeleton *object;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  guint n;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Acquired a message bus connection\n");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  /* Create a new org.freedesktop.DBus.ObjectManager rooted at /example/Animals */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  manager = g_dbus_object_manager_server_new ("/example/Animals");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for (n = 0; n <  10 ;  n + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gchar *s;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ExampleAnimal *animal;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      /* Create a new D-Bus object at the path /example/Animals/N where N is 000..009 */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      s = g_strdup_printf ("/example/Animals/%03d", n);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      object = example_object_skeleton_new (s);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_free (s);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      /* Make the newly created object export the interface
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       *  org.gtk.GDBus.Example.ObjectManager.Animal (note
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       *  that @object  takes its own reference to @animal ).
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      animal = example_animal_skeleton_new ();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_animal_set_mood (animal, "Happy");
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      example_object_skeleton_set_animal (object, animal);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_object_unref (animal);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      /* Cats are odd animals - so some of our objects implement the
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       *  org.gtk.GDBus.Example.ObjectManager.Cat interface in addition
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       *  to the .Animal interface
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if (n % 2 == 1)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ExampleCat *cat;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cat = example_cat_skeleton_new ();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          example_object_skeleton_set_cat (object, cat);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          g_object_unref (cat);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      /* Handle Poke() D-Bus method invocations on the .Animal interface */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_signal_connect (animal,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        "handle-poke",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        G_CALLBACK (on_animal_poke),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        NULL); /* user_data */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      /* Export the object (@manager  takes its own reference to @object ) */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_object_unref (object);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  /* Export all objects */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_dbus_object_manager_server_set_connection (manager, connection);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_name_acquired (GDBusConnection *connection,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  const gchar     *name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  gpointer         user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Acquired the name %s\n", name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_name_lost (GDBusConnection *connection,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              const gchar     *name,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              gpointer         user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Lost the name %s\n", name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gint
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								main (gint argc, gchar *argv[])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GMainLoop *loop;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  guint id;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  loop = g_main_loop_new (NULL, FALSE);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  id = g_bus_own_name (G_BUS_TYPE_SESSION,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       "org.gtk.GDBus.Examples.ObjectManager",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       on_bus_acquired,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       on_name_acquired,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       on_name_lost,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       loop,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_main_loop_run (loop);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_bus_unown_name (id);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_main_loop_unref (loop);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return 0;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								This, on the other hand, is a client-side application using generated code:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```c
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#include "gdbus-object-manager-example/objectmanager-gen.h"
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* ---------------------------------------------------------------------------------------------------- */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								print_objects (GDBusObjectManager *manager)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GList *objects;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GList *l;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Object manager at %s\n", g_dbus_object_manager_get_object_path (manager));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  objects = g_dbus_object_manager_get_objects (manager);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  for (l = objects; l != NULL; l = l->next)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ExampleObject *object = EXAMPLE_OBJECT (l->data);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      GList *interfaces;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      GList *ll;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_print (" - Object at %s\n", g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (object));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for (ll = interfaces; ll != NULL; ll = ll->next)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          GDBusInterface *interface = G_DBUS_INTERFACE (ll->data);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          g_print ("   - Interface %s\n", g_dbus_interface_get_info (interface)->name);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          /* Note that @interface  is really a GDBusProxy instance - and additionally also
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *  an ExampleAnimal or ExampleCat instance - either of these can be used to
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *  invoke methods on the remote object. For example, the generated function
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *   void example_animal_call_poke_sync (ExampleAnimal  *proxy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *                                       gboolean        make_sad,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *                                       gboolean        make_happy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *                                       GCancellable   *cancellable,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *                                       GError        **error);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *  can be used to call the Poke() D-Bus method on the .Animal interface.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *  Additionally, the generated function
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *   const gchar *example_animal_get_mood (ExampleAnimal *object);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           *  can be used to get the value of the :Mood property.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_list_free_full (interfaces, g_object_unref);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_list_free_full (objects, g_object_unref);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_object_added (GDBusObjectManager *manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 GDBusObject        *object,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 gpointer            user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gchar *owner;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Added object at %s (owner %s)\n", g_dbus_object_get_object_path (object), owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_free (owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_object_removed (GDBusObjectManager *manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   GDBusObject        *object,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   gpointer            user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gchar *owner;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Removed object at %s (owner %s)\n", g_dbus_object_get_object_path (object), owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_free (owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_notify_name_owner (GObject    *object,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      GParamSpec *pspec,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      gpointer    user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gchar *name_owner;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  name_owner = g_dbus_object_manager_client_get_name_owner (manager);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("name-owner: %s\n", name_owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_free (name_owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static void
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       GDBusObjectProxy         *object_proxy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       GDBusProxy               *interface_proxy,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       GVariant                 *changed_properties,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       const gchar *const       *invalidated_properties,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       gpointer                  user_data)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GVariantIter iter;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const gchar *key;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GVariant *value;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gchar *s;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("Properties Changed on %s:\n", g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_variant_iter_init (& iter, changed_properties);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while (g_variant_iter_next (& iter, "{& sv}", & key, & value))
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      s = g_variant_print (value, TRUE);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_print ("  %s -> %s\n", key, s);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_variant_unref (value);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_free (s);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								gint
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								main (gint argc, gchar *argv[])
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GDBusObjectManager *manager;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GMainLoop *loop;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GError *error;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gchar *name_owner;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  manager = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  loop = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  loop = g_main_loop_new (NULL, FALSE);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  error = NULL;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  manager = example_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            "org.gtk.GDBus.Examples.ObjectManager",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            "/example/Animals",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            NULL, /* GCancellable */
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            &error); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (manager == NULL)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_printerr ("Error getting object manager client: %s", error->message);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      g_error_free (error);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      goto out;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_print ("name-owner: %s\n", name_owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_free (name_owner);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  print_objects (manager);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_signal_connect (manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "notify::name-owner",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    G_CALLBACK (on_notify_name_owner),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_signal_connect (manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "object-added",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    G_CALLBACK (on_object_added),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_signal_connect (manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "object-removed",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    G_CALLBACK (on_object_removed),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_signal_connect (manager,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "interface-proxy-properties-changed",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    G_CALLBACK (on_interface_proxy_properties_changed),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    NULL);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  g_main_loop_run (loop);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 out:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (manager != NULL)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    g_object_unref (manager);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if (loop != NULL)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    g_main_loop_unref (loop);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return 0;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```