Open-source project
diwic/dbus-rs avatar
diwic/dbus-rs

dbus-rs gives Rust a native D-Bus story, server side included

D-Bus binding for the Rust language

673 stars144 forksRustNOASSERTION

At a glance

What is it?
dbus-rs is a family of Rust crates for talking D-Bus, with a blocking client, a Tokio integration, a codegen tool and two server frameworks. It suits a Rust developer who needs to speak the protocol rather than wrap it, and it is the wrong dependency for an application that only needs to read one well-known service.
Who is it for?
dbus-rs is a good fit for a Rust program that has to own a bus name, expose a D-Bus interface, or integrate with Tokio, because the server frameworks and the code generator are the hard parts and they are already here. It is the wrong dependency if all you need is a value from one well-known service, where the direct protocol client in your ecosystem of choice is less code.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 44 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One repository, many crates, and the split is the design

dbus-rs is a Cargo workspace rather than a single crate, and the layout explains what the project actually is. The workspace members listed in Cargo.toml are libdbus-sys, dbus, dbus-tokio, dbus-codegen, dbus-codegen-tests, dbus-crossroads, dbus-native, dbus-strings, dbus-tree and libdbus-src, with dbus-futures and dbus-native-channel explicitly excluded from the workspace. At the bottom of that stack sits libdbus-sys, the raw FFI bindings to libdbus, and libdbus-src, the vendored source of the C library. Above them, dbus is the main crate you would depend on, and then the rest are choices rather than requirements. dbus-tokio integrates D-Bus with Tokio. dbus-codegen installs a binary tool that generates Rust code from D-Bus XML introspection data. dbus-crossroads builds method dispatching servers, and dbus-tree does the same job with what the readme calls a legacy design. dbus-native and dbus-strings exist for the native and string flavours of the protocol, and dbus-native-channel for a channel oriented variant. The practical upshot is that you pull in one crate for a client and you opt into the rest.

Three ways to hold a connection, and they are not interchangeable

The readme names the connection types directly. You use blocking::Connection to connect to the session or system bus, and the alternative is SyncConnection or LocalConnection. That choice is the first real decision, and it is the one most likely to surprise someone arriving from an async-first Rust background. The blocking connection is the one the examples use, and the example client opens a session bus connection, wraps it in a proxy that makes it easy to send method calls to a specific destination and path, and then makes the call. The proxy is created with a destination name, an object path and a timeout of 5000 milliseconds in the example. The dbus-tokio crate exists precisely so you do not have to choose blocking, and it is listed as a separate crate with its own examples including a tokio server and an advanced tokio server. The vendored feature links libdbus statically into the final executable, which matters when you want a self-contained binary rather than a dynamic link against a system library, and the futures feature pulls in the futures crate to enable the nonblock module used by dbus-tokio.

The client example is short enough to read in one go

The client example in the readme opens a connection to the session bus and asks for a list of all names currently present, which is a reasonable first program because the reply is a plain list of strings. The method call itself is worth looking at, because the tuple shapes carry the whole argument convention:

rust
    // 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", ())?;

The input is a zero tuple and the output destructures into a single element tuple, so the Rust type mirrors the D-Bus signature directly. The general pattern extends to arguments of all types, and the readme points at an argument guide for the details, which is the file to read before you send anything with a non-trivial signature. Errors come back through the same Result mechanism, since the example function returns Result<(), Box<dyn std::error::Error>>. The examples directory holds more client code beyond this one, including a properties example, a signal matching example, an rtkit example and a monitor example, which together cover the four common interaction shapes on a bus.

Two server frameworks, and crossroads is the one the author points at

If you want to serve D-Bus rather than consume it, you pick a dispatching framework, and the readme is openly opinionated about which. In 0.9 the dbus::tree module moved out into the separate dbus-tree crate, and the readme says to consider migrating to dbus-crossroads instead, calling dbus-tree a legacy design. The two examples show the same job done differently. The dbus-tree version builds a Factory, adds an object path with a method, and then loops calling c.process with a one second duration, which is the shape of a simple event loop. The dbus-crossroads version registers an interface with a closure and inserts it at a path, then calls cr.serve to run it:

rust
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)?;

The request_name call is what claims the bus name, and the three booleans that follow are the standard request_name arguments. The crossroads form reads like a router table, one method declaration per interface, and the closure receives the arguments as a typed tuple. Standard D-Bus interfaces, namely introspection, properties and object manager, are supported. Both frameworks have their own example files in the repository, server_cr.rs and the advanced variants for crossroads, server.rs and adv_server.rs for tree.

Code generation from introspection XML saves the boilerplate

The dbus-codegen crate is the piece that removes the tedium, and it is worth knowing about before you hand-write interface bindings. It installs a binary tool which generates Rust code from D-Bus XML introspection data, and the readme points at the crate's own readme for an introduction to how to use it. The argument types that a service exposes are described in XML that the bus already publishes, so the codegen path is: find the interface XML, generate the Rust types and stubs, and wire the generated code into your handler. A separate dbus-codegen-tests crate sits in the workspace, which suggests the generator has its own test coverage rather than relying only on the hand written examples. The examples in this repository show the other way round, the manual construction of a method with its argument names and return values spelled out. So the codebase documents both approaches, manual for understanding the protocol and codegen for production use. The dbus-strings crate, which handles the string flavour of the protocol, is where generated code for that variant would be aimed.

Maturity, licence and the version history you have to plan for

The readme makes a measured claim about stability. The main dbus crate is fairly mature and the features you need should be all there, and breaking changes can still happen but not often. Two specific transitions are documented so you can plan an upgrade. In 0.9 the dbus::tree module moved to the dbus-tree crate, with a pointer to dbus-crossroads as the alternative. And if you are on 0.6.x and want to move to later versions, the readme links a changes document for dbus-rs 0.7. That is a real pattern to plan for, a project that keeps its API mostly stable but does move pieces into their own crates. On licensing, the readme states the code is Apache 2.0 and MIT dual licensed, and that code submitted in pull requests, discussions or issues is assumed to carry that licence unless stated otherwise. The repository has LICENSE-APACHE and LICENSE-MIT files at the root, and the project metadata records the licence as a custom one that GitHub cannot classify, which is what a dual licence looks like to that field. The last push was on 2026-09-09, and there are no GitHub releases, so the crates.io published versions are the artefacts you can pin to, and the repository history is where you watch for what comes next.

Editorial conclusion

dbus-rs is a good fit for a Rust program that has to own a bus name, expose a D-Bus interface, or integrate with Tokio, because the server frameworks and the code generator are the hard parts and they are already here. It is the wrong dependency if all you need is a value from one well-known service, where the direct protocol client in your ecosystem of choice is less code. Verify first that the crate version you pull exposes the API you expect, since breaking changes can still happen even though the readme calls the main crate fairly mature, and that the dual Apache 2.0 and MIT licensing covers your use. The last push was on 2026-09-09 and the repository publishes no GitHub releases, so the crates.io versions are the artefact to pin.

Frequently asked questions

Which crate should I use to talk D-Bus from Rust?

The main dbus crate for a blocking client, using blocking::Connection for the session or system bus, and the dbus-tokio crate if your program is async. For serving a bus name, dbus-crossroads is the recommended dispatching framework, while dbus-tree is described as a legacy design.

How do I generate Rust code from a D-Bus interface?

Use the dbus-codegen crate, which installs a binary tool that generates Rust code from D-Bus XML introspection data. The crate's own readme in the repository introduces how to use it.

What licence is dbus-rs released under?

The code is Apache 2.0 and MIT dual licensed, with LICENSE-APACHE and LICENSE-MIT at the repository root. Contributions in pull requests, discussions or issues are assumed to carry that licence unless stated otherwise.

How do I make the dbus crate link libdbus statically?

Enable the vendored feature, which links libdbus statically into the final executable. The futures feature is separate, it makes dbus depend on the futures crate and enables the nonblock module used by dbus-tokio.

Are there breaking changes in dbus-rs?

The readme says the main crate is fairly mature and breaking changes can still happen, but not often. In 0.9 the dbus::tree module moved to the dbus-tree crate, and there is a separate document listing the changes in dbus-rs 0.7 for users coming from 0.6.x.

Official sources

  1. diwic/dbus-rs on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/diwic-dbus-rs.svg)](https://hysenlabs.com/projects/diwic-dbus-rs)

Was this useful?