zbus 2.0.0-beta.6

API for D-Bus communication
Documentation

This crate provides the main API you will use to interact with D-Bus from Rust. It takes care of the establishment of a connection, the creation, sending and receiving of different kind of D-Bus messages (method calls, signals etc) for you.

zbus crate is currently Linux-specific[^otheros].

Getting Started

The best way to get started with zbus is the book, where we start with basic D-Bus concepts and explain with code samples, how zbus makes D-Bus easy.

Example code

Client

This code display a notification on your Freedesktop.org-compatible OS:

use std::collections::HashMap;
use std::error::Error;

use zbus::dbus_proxy;
use zvariant::Value;

#[dbus_proxy(
interface = "org.freedesktop.Notifications",
default_service = "org.freedesktop.Notifications",
default_path = "/org/freedesktop/Notifications"
)]
trait Notifications {
fn notify(
&self,
app_name: &str,
replaces_id: u32,
app_icon: &str,
summary: &str,
body: &str,
actions: &[&str],
hints: HashMap<&str, &Value<'_>>,
expire_timeout: i32,
) -> zbus::Result<u32>;
}

fn main() -> Result<(), Box<dyn Error>> {
let connection = zbus::Connection::session()?;

// `dbus_proxy` macro creates `NotificationProxy` based on `Notifications` trait.
let proxy = NotificationsProxy::new(&connection)?;
let reply = proxy.notify(
"my-app",
0,
"dialog-information",
"A summary",
"Some body",
&[],
HashMap::new(),
5000,
)?;
dbg!(reply);

Ok(())
}

Server

A simple service that politely greets whoever calls its SayHello method:

use std::error::Error;
use zbus::{dbus_interface, fdo, ObjectServer, Connection};

struct Greeter {
count: u64
};

#[dbus_interface(name = "org.zbus.MyGreeter1")]
impl Greeter {
fn say_hello(&mut self, name: &str) -> String {
self.count += 1;
format!("Hello {}! I have been called: {}", name, self.count)
}
}

fn main() -> Result<(), Box<dyn Error>> {
let connection = Connection::session()?;
let mut object_server = ObjectServer::new(&connection)
.request_name("org.zbus.MyGreeter")?;
let mut greeter = Greeter { count: 0 };
object_server.at("/org/zbus/MyGreeter", greeter)?;
loop {
if let Err(err) = object_server.try_handle_next() {
eprintln!("{}", err);
}
}
}

You can use the following command to test it:

$ busctl --user call \
org.zbus.MyGreeter \
/org/zbus/MyGreeter \
org.zbus.MyGreeter1 \
SayHello s "Maria"
Hello Maria!
$

Asynchronous API

Runtime-agnostic async/await-compatible API for both (not so) low-level message handling and high-level client-side proxy is also provided. High-level server-side API coming soon.

Compatibility with async runtimes

zbus is runtime-agnostic and should work out of the box with different Rust async runtimes. However, in order to achieve that, zbus spawns a thread per connection to handle various internal tasks. If that is something you would like to avoid, you need to:

[^otheros]: Support for other OS exist, but it is not supported to the same extent. D-Bus clients in javascript (running from any browser) do exist though. And zbus may also be working from the browser sometime in the future too, thanks to Rust 🦀 and WebAssembly 🕸.