Archive for December 16, 2010

D-BUS Tips 3.0: Performing asynchronous/synchronous method invocations and dbus-binding-tool

To easy perform a synchronous remote method invocation you have just to use GLib bindings  for DBus Proxy API (DBusGProxy), that is our first example. The second example shows how to use generated code by dbus-binding-tool to implement remote calls faster. Examples bellow are implemented accessing org.freedesktop.NetworkManager interface of NetworkManager API.

Example 1


int main()
{
	g_type_init();

	GError *error = NULL;
	DBusGConnection *conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

	if (error != NULL) {
		g_error("D-BUS Connection error: %s", error->message);
		g_error_free(error);
	}

	if (!conn) {
		g_error("D-BUS connection cannot be created");
		return EXIT_FAILURE;
	}

	DBusGProxy *proxy = dbus_g_proxy_new_for_name(conn,
			"org.freedesktop.NetworkManager",
			"/org/freedesktop/NetworkManager",
			"org.freedesktop.NetworkManager");

	if (!proxy) {
		g_error("Cannot create proxy");
		return EXIT_FAILURE;
	}

	g_message("Calling NetworkManager.sate synchronously");
	guint state;
	GError *error = NULL;
	if (!dbus_g_proxy_call(proxy, "state", &error, G_TYPE_INVALID,
			G_TYPE_UINT, &state, G_TYPE_INVALID)) {
		if (error->domain == DBUS_GERROR && error->code
					== DBUS_GERROR_REMOTE_EXCEPTION) {
			g_error("Caught remote method exception %s: %s",
					dbus_g_error_get_name(error),
					error->message);
		} else {
			g_error("D-BUS: %s", error->message);
		}
	}
	print_network_manager_state(state);

	g_object_unref(proxy);
	dbus_g_connection_unref(conn);
	return EXIT_SUCCESS;
}

The code is self explaining. Be careful to use the right type parameters, otherwise the call will not work, at D-Bus tutorial page you can find GLib – DBus type mapping. If you want to use more complex types outside this mapping, GLib may show you the message “No marshaller for signature of …” and you will need to register a custom marshaller to this type, but this is a subject for future posts.

Example 2

A faster way to call a remote method is to generate client stub. First you need to get XML API of object interface, you can use d-feet tool to call DBus Introspectable interface and get that.

instrospect

Then execute the following command passing network-manager-api.xml file:


dbus-binding-tool --mode=glib-client network-manager-api.xml >  network-manager-client-stub.h

And you will simply get the code ready to execute D-BUS calls and they are properly typed according to method signatures. The example show you an asynchronous call using the stub:

#include "network-manager-client-stub.h"

void network_state_callback(DBusGProxy *proxy, guint state, GError *error, gpointer userdata)
{
	print_network_manager_state(state);
	g_main_loop_quit(loop);
}

static GMainLoop *loop;
int main()
{
	loop = g_main_loop_new(NULL, FALSE);
	g_type_init();

	GError *error = NULL;
	DBusGConnection *conn = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);

	if (error != NULL) {
		g_error("D-BUS Connection error: %s", error->message);
		g_error_free(error);
	}

	if (!conn) {
		g_error("D-BUS connection cannot be created");
		return EXIT_FAILURE;
	}

	DBusGProxy *proxy = dbus_g_proxy_new_for_name(conn,
			"org.freedesktop.NetworkManager",
			"/org/freedesktop/NetworkManager",
			"org.freedesktop.NetworkManager");

	if (!proxy) {
		g_error("Cannot create proxy");
		return EXIT_FAILURE;
	}

	g_message("Calling NetworkManager.sate asynchronously");
	org_freedesktop_NetworkManager_state_async(proxy, network_state_callback , NULL);

	g_message("Waiting D-BUS callback");
	g_main_loop_run(loop);

	g_message("Exiting glib mainloop");

	g_main_loop_unref(loop);
	g_object_unref(proxy);
	dbus_g_connection_unref(conn);
	return EXIT_SUCCESS;
}

See full code example in method-invocation.c at dbus-glib-sample project.

December 16, 2010 at 10:09 am Leave a comment


Calendar

December 2010
M T W T F S S
« Nov    
 12345
6789101112
13141516171819
20212223242526
2728293031  

Posts by Month

Posts by Category


Follow

Get every new post delivered to your Inbox.