
zbus阻塞API使用指南让同步代码也能轻松玩转D-Bus【免费下载链接】zbusRust D-Bus crate.项目地址: https://gitcode.com/gh_mirrors/zb/zbuszbus 是 Rust 生态中最流行的 D-Bus 通信库自 2.0 版本起 API 以异步为主。但如果你只想写一个简单的命令行工具async/await反而成了负担。别担心——zbus 在blocking模块下内置了完整的阻塞 API用blocking::Connection建立 D-Bus 连接、用blocking::Proxy调用远程方法、用blocking::ObjectServer发布服务全部同步完成无需引入任何异步运行时。为什么需要 zbus 阻塞 API zbus 的异步 API 适合高并发服务但对于这类场景就显得杀鸡用牛刀了写一个修改屏幕亮度、查询系统信息的小工具快速原型验证 D-Bus 服务接口在同步风格的代码库里调用系统服务。zbus 的设计目标之一就是易用阻塞 API 正是为此而生。它是一层薄封装每个阻塞类型内部都会用block_on启动一个小运行时把对应的异步调用转成阻塞调用实现见zbus/src/blocking/mod.rs。快速建立 D-Bus 阻塞连接与异步Connection的唯一区别就是换个类型方法完全一一对应。三个最常用的入口方法用途Connection::session()连接用户会话总线桌面程序首选Connection::system()连接系统总线硬件、网络等系统级服务blocking::connection::Builder高级构建器支持自定义地址、请求名称等use zbus::blocking::Connection; // 一行代码连上会话总线 let connection Connection::session()?; 不想手写地址Builder还提供address()、unix_stream()等构建方式细节可参考zbus/src/blocking/connection/builder.rs。用 blocking::Proxy 调用 D-Bus 方法客户端核心是blocking::Proxy。最简洁的用法是直接向目标服务点名调用方法use zbus::blocking::{Connection, Proxy}; let connection Connection::session()?; let proxy Proxy::new( connection, org.freedesktop.DBus, /org/freedesktop/DBus, org.freedesktop.DBus, )?; // 同步阻塞地调用 GetId直接拿到 String 结果 let id: String proxy.call(GetId, ())?;如果配合proxy宏使用宏会自动为你生成XxxProxyBlocking类型的包装宏的写法与异步版完全一致只是类型名多了Blocking后缀。项目自带的zbus/examples/screen-brightness.rs就是一个绝佳范例十几行同步代码实现了调用 GNOME 服务调节屏幕亮度非常适合作为入门参考。同步接收 D-Bus 信号Iterator 风格 ✨这是阻塞 API 与异步版最容易被忽略的差异阻塞版接收信号的实现的是标准库的std::iter::Iterator而非futures::stream::Stream。所以不用await直接next()循环等待即可let mut location_updated client.receive_location_updated()?; // 阻塞等待下一个信号到来 let signal location_updated.next()?; let args signal.args()?;监听属性变更同理调用receive_xxx_changed()后不断调用next()代码读起来和读取文件迭代器一样自然。编写 D-Bus 服务blocking::ObjectServer服务端使用与每个blocking::Connection关联的blocking::ObjectServer源码在zbus/src/blocking/object_server.rs。#[interface]宏允许你编写非异步方法#[interface(name org.zbus.MyGreeter1)] impl Greeter { // 普通同步方法即可无需 async fn say_hello(self, name: str) - String { format!(Hello {}!, name) } #[zbus(property)] fn greeter_name(self) - str { self.name } } let _handle connection::Builder::session()? .name(org.zbus.MyGreeter)? .serve_at(/org/zbus/MyGreeter, greeter)? .build()?;⚠️ 注意虽然方法体是同步的但它们实际仍运行在异步上下文里因此方法内部不能直接再调用阻塞 API详见下文避坑指南。避坑指南3 个使用限制 ⚠️不要在 async 上下文中使用阻塞 API阻塞方法内部自带block_on运行时再套进async上下文会触发经典的 async sandwich 问题导致 panic 或死锁。需要跨边界时可借助tokio::task::spawn_blocking、async-std 的spawn_blocking或blockingcrate 解决。服务端方法里同样不能用阻塞 API如前所述#[interface]的非异步方法仍由异步上下文调用方法体内如需阻塞操作同样要走spawn_blocking类方案。blocking-api特性默认开启但可被意外关闭自 zbus 5.0 起阻塞 API 由 Cargo featureblocking-api控制默认启用。如果你在Cargo.toml中关闭了 default features 又没显式加回阻塞 API 会直接编译失败。源码与文档速查 内容路径阻塞 API 模块总览zbus/src/blocking/mod.rs阻塞连接与构建器zbus/src/blocking/connection/mod.rs、zbus/src/blocking/connection/builder.rs阻塞客户端代理zbus/src/blocking/proxy/mod.rs阻塞对象服务器zbus/src/blocking/object_server.rs官方手册阻塞章节book/src/blocking.md实战示例屏幕亮度工具zbus/examples/screen-brightness.rs上手顺序建议先读book/src/blocking.md再照着screen-brightness.rs写你自己的第一个同步 D-Bus 客户端最后需要发布服务时再研究blocking::ObjectServer。掌握这三步zbus 的阻塞 API 就完全属于你的了 【免费下载链接】zbusRust D-Bus crate.项目地址: https://gitcode.com/gh_mirrors/zb/zbus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考