README.md
1# zbus
2
3[![](https://docs.rs/zbus/badge.svg)](https://docs.rs/zbus/) [![](https://img.shields.io/crates/v/zbus)](https://crates.io/crates/zbus)
4
5This is the main subcrate of the [zbus] project, that provides the main API you will use to interact
6with D-Bus from Rust. It takes care of the establishment of a connection, the creation, sending and
7receiving of different kind of D-Bus messages (method calls, signals etc) for you.
8
9**Status:** Stable.
10
11## Getting Started
12
13The best way to get started with zbus is the [book](https://dbus.pages.freedesktop.org/zbus/),
14where we start with basic D-Bus concepts and explain with code samples, how zbus makes D-Bus easy.
15
16## Example code
17
18### Client
19
20This code display a notification on your Freedesktop.org-compatible OS:
21
22```rust,no_run
23use std::{collections::HashMap, error::Error};
24
25use zbus::{Connection, dbus_proxy};
26use zvariant::Value;
27
28#[dbus_proxy(
29 interface = "org.freedesktop.Notifications",
30 default_service = "org.freedesktop.Notifications",
31 default_path = "/org/freedesktop/Notifications"
32)]
33trait Notifications {
34 fn notify(
35 &self,
36 app_name: &str,
37 replaces_id: u32,
38 app_icon: &str,
39 summary: &str,
40 body: &str,
41 actions: &[&str],
42 hints: &HashMap<&str, &Value<'_>>,
43 expire_timeout: i32,
44 ) -> zbus::Result<u32>;
45}
46
47// Although we use `async-std` here, you can use any async runtime of choice.
48#[async_std::main]
49async fn main() -> Result<(), Box<dyn Error>> {
50 let connection = Connection::session().await?;
51
52 // `dbus_proxy` macro creates `NotificationProxy` based on `Notifications` trait.
53 let proxy = NotificationsProxy::new(&connection).await?;
54 let reply = proxy.notify(
55 "my-app",
56 0,
57 "dialog-information",
58 "A summary",
59 "Some body",
60 &[],
61 &HashMap::new(),
62 5000,
63 ).await?;
64 dbg!(reply);
65
66 Ok(())
67}
68```
69
70### Server
71
72A simple service that politely greets whoever calls its `SayHello` method:
73
74```rust,no_run
75use std::{
76 error::Error,
77 thread::sleep,
78 time::Duration,
79};
80use zbus::{ObjectServer, ConnectionBuilder, dbus_interface, fdo};
81
82struct Greeter {
83 count: u64
84}
85
86#[dbus_interface(name = "org.zbus.MyGreeter1")]
87impl Greeter {
88 // Can be `async` as well.
89 fn say_hello(&mut self, name: &str) -> String {
90 self.count += 1;
91 format!("Hello {}! I have been called: {}", name, self.count)
92 }
93}
94
95// Although we use `async-std` here, you can use any async runtime of choice.
96#[async_std::main]
97async fn main() -> Result<(), Box<dyn Error>> {
98 let greeter = Greeter { count: 0 };
99 let _ = ConnectionBuilder::session()?
100 .name("org.zbus.MyGreeter")?
101 .serve_at("/org/zbus/MyGreeter", greeter)?
102 .build()
103 .await?;
104
105 // Do other things or go to sleep.
106 sleep(Duration::from_secs(60));
107
108 Ok(())
109}
110```
111
112You can use the following command to test it:
113
114```bash
115$ busctl --user call org.zbus.MyGreeter /org/zbus/MyGreeter org.zbus.MyGreeter1 SayHello s "Maria"
116Hello Maria!
117s
118```
119
120## Blocking API
121
122While zbus is primarily asynchronous (since 2.0), [blocking wrappers][bw] are provided for
123convenience.
124
125## Compatibility with async runtimes
126
127zbus is runtime-agnostic and should work out of the box with different Rust async runtimes. However,
128in order to achieve that, zbus spawns a thread per connection to handle various internal tasks. If
129that is something you would like to avoid, you need to:
130 * Use [`ConnectionBuilder`] and disable the `internal_executor` flag.
131 * Ensure the [internal executor keeps ticking continuously][iektc].
132
133Moreover, by default zbus makes use of [`async-io`] for all I/O, which also launches its own thread
134to run its own internal executor.
135
136### Special tokio support
137
138Since [`tokio`] is the most popular async runtime, zbus provides an easy way to enable tight
139integration with it without you having to worry about any of the above: Enabling the `tokio` feature
140and disabling the default `async-io` feature:
141
142```toml
143# Sample Cargo.toml snippet.
144[dependencies]
145zbus = { version = "2", default-features = false, features = ["tokio"] }
146```
147
148That's it! No threads launched behind your back by zbus (directly or indirectly) now and no need to
149tick any executors etc.
150
151[zbus]: https://gitlab.freedesktop.org/dbus/zbus/-/blob/main/README.md
152[bw]: https://docs.rs/zbus/2.0.0/zbus/blocking/index.html
153[iektc]: https://docs.rs/zbus/2.0.0/zbus/struct.Connection.html#examples-1
154[`ConnectionBuilder`]: https://docs.rs/zbus/2.0.0/zbus/struct.ConnectionBuilder.html
155[`tokio`]: https://crates.io/crates/tokio
156[`async-io`]: https://crates.io/crates/async-io
157[LICENSE-MIT]: https://gitlab.freedesktop.org/dbus/zbus/-/blob/main/LICENSE-MIT
158