A Rust API for D-Bus communication. The goal is to provide a safe and simple high- and low-level API akin to GDBus, that doesn't depend on C libraries.
The project is divided into the following subcrates:
zbus
andzbus_macros
: The main subcrates that provide the API to interact with D-Bus.zvariant
andzvariant_derive
: API for encoding/decoding of data to/from D-Bus wire format.zbus_names
: A collection of types for various D-Bus bus names.zbus_xmlgen
: A developer tool to generate Rust code from D-Bus XML interface descriptions.zbus_polkit
: A crate to interact with PolicyKit.
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.
A simple service that politely greets whoever calls its SayHello
method:
use std::{error::Error, future::pending};
use zbus::{ConnectionBuilder, dbus_interface};
struct Greeter {
count: u64
}
#[dbus_interface(name = "org.zbus.MyGreeter1")]
impl Greeter {
// Can be `async` as well.
fn say_hello(&mut self, name: &str) -> String {
self.count += 1;
format!("Hello {}! I have been called {} times.", name, self.count)
}
}
// Although we use `async-std` here, you can use any async runtime of choice.
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
let greeter = Greeter { count: 0 };
let _conn = ConnectionBuilder::session()?
.name("org.zbus.MyGreeter")?
.serve_at("/org/zbus/MyGreeter", greeter)?
.build()
.await?;
// Do other things or go to wait forever
pending::<()>().await;
Ok(())
}
You can use the following command to test it:
$ busctl --user call org.zbus.MyGreeter /org/zbus/MyGreeter org.zbus.MyGreeter1 SayHello s "Maria"
s "Hello Maria! I have been called 1 times."
Now let's write the client-side code for MyGreeter
service:
use zbus::{Connection, Result, dbus_proxy};
#[dbus_proxy(
interface = "org.zbus.MyGreeter1",
default_service = "org.zbus.MyGreeter",
default_path = "/org/zbus/MyGreeter"
)]
trait MyGreeter {
async fn say_hello(&self, name: &str) -> Result<String>;
}
// Although we use `async-std` here, you can use any async runtime of choice.
#[async_std::main]
async fn main() -> Result<()> {
let connection = Connection::session().await?;
// `dbus_proxy` macro creates `MyGreaterProxy` based on `Notifications` trait.
let proxy = MyGreeterProxy::new(&connection).await?;
let reply = proxy.say_hello("Maria").await?;
println!("{reply}");
Ok(())
}
If you need help in using these crates, are looking for ways to contribute, or just want to hang out
with the cool kids, please come chat with us in the
#zbus:matrix.org
Matrix room. If something doesn't seem
right, please file an issue.
All crates are currently Unix-only with Linux as the main (and tested) target and will fail to build on non-unix. This is hopefully a temporary limitation. Moreover, integration tests of zbus crate currently require a session bus running on the build host.
MIT license LICENSE-MIT
dbus-rs relies on the battle tested libdbus C library to send and receive messages. Companion crates add Tokio support, server builder without macros, and code generation.
There are many other D-Bus crates out there with various levels of maturity and features.