Dbus | C API (Part 1)

My first experience with Dbus started in 2010. My challenge was to manage the communication between the differents parts as: decoder (C), UI (C++), the xosd interface, and the remote controller interface  (C).

What’s Dbus ?

Dbus is a message bus system, it allows applications to communicate to each other in a simple way. Currently the communicating applications are on one computer, or through unencrypted TCP/IP suitable for use behind a firewall with shared NFS home directories. It is simultaneously an Inter-Process Communication (IPC) and Remote Procedure Calling (RPC) mechanism. In Dbus we have two kind of sessions:

  • A “system bus” for communicating between system applications and user sessions
  • A “session bus” for exchanging data between applications in a desktop environments

Code

Let’s go now to the real life: To connect to Dbus you should

  • Initialize the errors

DBusError err;
DBusConnection* conn;
int ret;
// initialize the errors
dbus_error_init(&err);

  • Connect to the dbus

conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
 fprintf(stderr, "Connection Error (%s)\n", err.message);
 dbus_error_free(&err);
}
if (NULL == conn) {
 exit(1);
}

    • Now, you need to request a name on the bus

ret = dbus_bus_request_name(conn, "test.method.server",
                            DBUS_NAME_FLAG_REPLACE_EXISTING
                            , &err);
if (dbus_error_is_set(&err)) {
  fprintf(stderr, "Name Error (%s)\n", err.message);
  dbus_error_free(&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
  exit(1);
}

  • After you have finished with the bus, you should close the connection:
dbus_connection_close(conn);
  1. Sending a signal

This is the simplest operation, the below code do the entirely operation

dbus_uint32_t serial = 0; // unique number to associate replies with requests
DBusMessage* msg;
DBusMessageIter args;

// create a signal and check for errors
msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal
"test.signal.Type", // interface name of the signal
"Test"); // name of the signal
if (NULL == msg)
{
fprintf(stderr, "Message Null\n");
exit(1);
}

// append arguments onto signal
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}

// send the message and flush the connection
if (!dbus_connection_send(conn, msg, &serial)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
dbus_connection_flush(conn);

// free the message
dbus_message_unref(msg);
  1. Receiving a signal

These operation requires reading message from the bus. To receive a signal you have to tell the bus what signals you are interested in so they are sent to your application, then you read messages off the bus and can check what type they are and what interfaces and signal names each signal represents.

// add a rule for which messages we want to see
dbus_bus_add_match(conn,
"type='signal',interface='test.signal.Type'",
&err); // see signals from the given interface
dbus_connection_flush(conn);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
// loop listening for signals being emmitted
while (true) {
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);

// loop again if we haven't read a message
if (NULL == msg) {
sleep(1);
continue;
}

// check if the message is a signal from the correct interface and with the correct name
if (dbus_message_is_signal(msg, "test.signal.Type", "Test")) {
// read the parameters
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "Message has no arguments!\n");
else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
fprintf(stderr, "Argument is not string!\n");
else {
dbus_message_iter_get_basic(&args, &sigvalue);
printf("Got Signal with value %s\n", sigvalue);
}
}

// free the message
dbus_message_unref(msg);
 }

I hope that will be a good light introduction to the Dbus system.