57个稳定版本

4.4.0 2024年7月22日
4.2.2 2024年5月20日
4.1.2 2024年2月25日
3.15.2 2024年2月25日
0.1.2 2020年7月7日

#3 in Unix APIs

Download history 150357/week @ 2024-05-03 149686/week @ 2024-05-10 157468/week @ 2024-05-17 152200/week @ 2024-05-24 163880/week @ 2024-05-31 150303/week @ 2024-06-07 156849/week @ 2024-06-14 168971/week @ 2024-06-21 165818/week @ 2024-06-28 154499/week @ 2024-07-05 168480/week @ 2024-07-12 166830/week @ 2024-07-19 170871/week @ 2024-07-26 164231/week @ 2024-08-02 167739/week @ 2024-08-09 154652/week @ 2024-08-16

688,425 月下载量
用于 439 个crate(142个直接使用)

MIT 许可证

1MB
25K SLoC

zbus

这是zbus项目的核心子crate,提供了与D-Bus交互的API。它负责建立连接,为您创建、发送和接收不同类型的D-Bus消息(方法调用、信号等)。

状态:稳定。

入门

了解zbus的最佳方式是书籍,其中我们从基本的DBus概念开始,并通过代码示例解释zbus如何让DBus变得简单。

示例代码

我们将创建一个简单的DBus服务和客户端来演示zbus的使用。请注意,这些示例假定您的机器上已设置DBus代理,并且有一个会话总线正在运行(必须设置DBUS_SESSION_BUS_ADDRESS环境变量)。在典型的Linux桌面会话中,这通常是保证的。

服务

一个简单的服务,当有人调用其SayHello方法时,会礼貌地问候

use std::{error::Error, future::pending};
use zbus::{connection, interface};

struct Greeter {
    count: u64
}

#[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 `tokio` here, you can use any async runtime of choice.
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let greeter = Greeter { count: 0 };
    let _conn = connection::Builder::session()?
        .name("org.zbus.MyGreeter")?
        .serve_at("/org/zbus/MyGreeter", greeter)?
        .build()
        .await?;

    // Do other things or go to wait forever
    pending::<()>().await;

    Ok(())
}

您可以使用以下命令进行测试

$ busctl --user call org.zbus.MyGreeter /org/zbus/MyGreeter org.zbus.MyGreeter1 SayHello s "Maria"
s "Hello Maria! I have been called 1 times."

客户端

现在让我们编写MyGreeter服务的客户端代码

use zbus::{Connection, Result, proxy};

#[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 `tokio` here, you can use any async runtime of choice.
#[tokio::main]
async fn main() -> Result<()> {
    let connection = Connection::session().await?;

    // `proxy` macro creates `MyGreaterProxy` based on `Notifications` trait.
    let proxy = MyGreeterProxy::new(&connection).await?;
    let reply = proxy.say_hello("Maria").await?;
    println!("{reply}");

    Ok(())
}

阻塞API

虽然zbus主要是异步的(自2.0版本以来),但为了方便,提供了阻塞包装器

与异步运行时的兼容性

zbus是运行时无关的,并且应该能够与不同的Rust异步运行时无缝工作。然而,为了实现这一点,zbus为每个连接创建一个线程来处理各种内部任务。如果您希望避免这种情况,您需要

此外,默认情况下,zbus使用async-io进行所有I/O,它也会启动自己的线程来运行自己的内部执行器。

特殊的tokio支持

由于 tokio 是最受欢迎的异步运行时,zbus 提供了一种简单的方法来实现与它的紧密集成,无需您担心上述任何内容:启用 tokio 功能

# Sample Cargo.toml snippet.
[dependencies]
# Also disable the default `async-io` feature to avoid unused dependencies.
zbus = { version = "3", default-features = false, features = ["tokio"] }

就是这样!现在 zbus 不会在您背后启动线程(直接或间接),也不需要勾选任何执行器等。😼

注意:在 Windows 上,目前需要 async-io 功能才能支持 UNIX 域套接字,请参阅 GitHub 上相应的 tokio 问题

依赖关系

~7–21MB
~312K SLoC