D-Bus bindings for Rust
- Use
blocking::Connection
to connect to the session or system bus. (OrSyncConnection
/LocalConnection
) - Use
Message
to send and receive messages. Get and append arguments of all types, see the argument guide for details. - Build method dispatching servers using the
dbus-crossroads
ordbus-tree
crates. Standard D-Bus interfaces (introspection, properties, object manager) are supported.
Breaking changes
The main dbus crate is fairly mature and the features you need should be all there. Breaking changes can still happen, but not often.
- In 0.9, the
dbus::tree
module moved to thedbus-tree
crate (but consider migrating todbus-crossroads
instead). - If you're currently using 0.6.x of dbus and want to upgrade to later versions, you can read changes in dbus-rs 0.7.
Additional crates
- dbus-crossroads for easy building of method dispatching servers.
- dbus-tokio integrates D-Bus with Tokio.
- dbus-codegen installs a binary tool which generates Rust code from D-Bus XML introspection data. The readme contains an introduction to how to use it.
- libdbus-sys contains the raw FFI bindings to libdbus.
- dbus-tree facitilates easy building of method dispatching servers (legacy design).
Invitation
You are hereby invited to participate in the development of these crates:
- If you have discovered what you believe is a bug, file an issue.
- If you have questions or comments that the documentation cannot answer in an easy way, start a discussion.
- If you have smaller improvements to code, documentation, examples etc, go ahead and submit a pull request. Larger pieces of work are better off discussed first.
The code is Apache 2.0 / MIT dual licensed. Any code submitted in Pull Requests, discussions or issues is assumed to have this license, unless explicitly stated otherwise.
Examples
Client
This example opens a connection to the session bus and asks for a list of all names currently present.
use dbus::blocking::Connection;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// First open up a connection to the session bus.
let conn = Connection::new_session()?;
// Second, create a wrapper struct around the connection that makes it easy
// to send method calls to a specific destination and path.
let proxy = conn.with_proxy("org.freedesktop.DBus", "/", Duration::from_millis(5000));
// Now make the method call. The ListNames method call takes zero input parameters and
// one output parameter which is an array of strings.
// Therefore the input is a zero tuple "()", and the output is a single tuple "(names,)".
let (names,): (Vec<String>,) = proxy.method_call("org.freedesktop.DBus", "ListNames", ())?;
// Let's print all the names to stdout.
for name in names { println!("{}", name); }
Ok(())
}
Examples of client code in the examples directory:
- client.rs (same as the above)
- properties.rs
- match_signal.rs
- rtkit.rs
- monitor.rs
Server
This example grabs the com.example.dbustest
bus name, adds the /hello
path
which implements the com.example.dbustest
interface, and specifies that this
interface has a Hello
method.
It then listens for incoming D-Bus method calls on this path and handles them accordingly.
dbus-crossroads:
let c = Connection::new_session()?;
c.request_name("com.example.dbustest", false, true, false)?;
let mut cr = Crossroads::new();
let token = cr.register("com.example.dbustest", |b| {
b.method("Hello", ("name",), ("reply",), |_, _, (name,): (String,)| {
Ok((format!("Hello {}!", name),))
});
});
cr.insert("/hello", &[token], ());
cr.serve(&c)?;
Examples of server code using dbus-crossroads
in the examples directory:
dbus-tree:
let c = Connection::new_session()?;
c.request_name("com.example.dbustest", false, true, false)?;
let f = Factory::new_fn::<()>();
let tree = f.tree(())
.add(f.object_path("/hello", ()).introspectable()
.add(f.interface("com.example.dbustest", ())
.add_m(f.method("Hello", (), |m| {
let n: &str = m.msg.read1()?;
let s = format!("Hello {}!", n);
Ok(vec!(m.msg.method_return().append1(s)))
}).inarg::<&str,_>("name")
.outarg::<&str,_>("reply")
)
).add(f.object_path("/", ()).introspectable());
tree.start_receive(&c);
loop { c.process(Duration::from_millis(1000))?; }
Examples of server code using dbus-tree
in the examples directory:
Features
The futures
feature makes dbus
depend on the futures
crate. This enables the nonblock
module (used by the dbus-tokio
crate).
The vendored
feature links libdbus statically into the final executable.
The stdfd
feature uses std's OwnedFd
instead of dbus own. (This will be the default in the next major release.)
The no-string-validation
feature skips an extra check that a specific string (e g a Path
, ErrorName
etc) conforms to the D-Bus specification, which might also make things a tiny bit faster. But - if you do so, and then actually send invalid strings to the D-Bus library, you might get a panic instead of a proper error.
Requirements
Default
Libdbus 1.6 or higher, and latest stable release of Rust. If you run Ubuntu (any maintained version should be okay), this means having the libdbus-1-dev
and pkg-config
packages installed while building, and the libdbus-1-3
package installed while running.
Vendored
If the vendored
feature is enabled, none of the default requirements.
The vendored
feature is the current recommended way to cross compile dbus-rs. More information and some other methods are mentioned here.
Alternatives
zbus and rustbus (stalled?) are D-Bus crates written completely in Rust (i e, no bindings to C libraries). Some more alternatives are listed here, but I'm not sure how usable they are.