12 个版本 (7 个破坏性更改)
0.12.0 | 2024 年 5 月 29 日 |
---|---|
0.11.0 | 2024 年 2 月 19 日 |
0.10.0 | 2021 年 10 月 13 日 |
0.9.1 | 2021 年 1 月 5 日 |
0.2.0 | 2017 年 11 月 11 日 |
#206 在 Unix API 中
每月下载量 8,312
用于 13 个 包(5 个直接使用)
530KB
10K SLoC
dbus-codegen-rust
此程序接受 D-Bus XML 检查数据,并生成调用和实现检查数据中接口的 Rust 代码。
示例
从这样的 D-Bus 接口
<node>
<interface name="org.example.test">
<method name="Foo">
<arg type="i" name="bar" direction="in"/>
<arg type="s" name="baz" direction="out"/>
</method>
<signal name="Laundry">
<arg type="b" name="eaten"/>
</signal>
</interface>
</node>
您可以选择生成以下三者之一
- 客户端代码(用于调用接口)
- 使用 dbus-crossroads 实现接口的服务器端代码
- 使用 dbus-tree 实现接口的服务器端代码
客户端和服务器端通用
- 一个用于调用/实现接口方法的 trait,如下所示
pub trait OrgExampleTest {
fn foo(&self, bar: i32) -> Result<String, dbus::Error>;
}
pub trait OrgExampleTest {
fn foo(&self, bar: i32) -> Result<String, dbus::MethodErr>;
}
对于属性,将生成 get_xx
和 set_xx
方法。目前没有 get_all
方法。
- 每个信号一个 struct,如下所示
#[derive(Debug, Default)]
pub struct OrgExampleTestLaundry {
pub eaten: bool,
}
impl dbus::SignalArgs for OrgExampleTestLaundry { /* code here */ }
客户端
- 将为
blocking::Proxy
、nonblock::Proxy
或ffidisp::ConnPath
实现 trait,这使得客户端调用方法变得容易,如下所示
use OrgExampleTest;
let myString = myProxy.foo(myInteger)?;
- 要捕获从服务器发出的信号,请这样做
use dbus::SignalArgs;
myConnection.add_match(OrgExampleTestLaundry::match_rule(None, None).into_static(), |laundrySignal| {
println!("Laundry was eaten: {:?}", laundrySignal.eaten);
})
服务器端 - dbus-crossroads
- 将生成一个注册
IfaceToken
的方法,如下所示
let token = register_org_example_test(&mut myCrossroads);
myCrossroads.insert("/", &[token], myData);
其中 myData 必须是实现了 OrgExampleTest
的类型。
服务器端 - dbus-tree
- 将生成一个方法,您可以通过调用它来获取
tree::Interface
,如下所示
myInterface = orgexampletest_server(&myFactory, ());
然后将此接口添加到 tree::ObjectPath
中,如 主页 所示。
此外,您还需要实现接口的方法,如下所示
impl OrgExampleTest for MyStruct {
type Err = tree::MethodErr;
fn foo(&self, bar: i32) -> Result<String, Self::Err> {
/* Your code here */
}
}
我一直在尝试不同的方法,以使生成的服务器函数能够到达实现的结构体,这由命令行参数 methodaccess
控制。
- 如果
methodaccess
是MethodInfo
,那么您需要实现MethodInfo
结构体的接口,如下所示
impl<M: tree::MethodType<D>, D> OrgExampleTest for tree::MethodInfo<M, D> {
type Err = tree::MethodErr;
fn foo(&self, bar: i32) -> Result<String, Self::Err> {
/* Your code here */
}
}
- 如果
methodaccess
是RefClosure
,那么您需要提供一个返回实现结构体引用的闭包。如果结构体存储在树中(这意味着实现tree::DataType
),这是一个很好的选项。
myInterface = orgexampletest_server(&myFactory, (), |m| m.path.get_data());
- 如果
methodaccess
是AsRefClosure
,那么您需要提供一个返回可以引用实现结构体的对象的闭包。在方法调用后,该对象会被丢弃。这很好地与Arc
/Rc
一起工作,如下所示
impl AsRef<dyn OrgExampleTest + 'static> for Rc<MyStruct> {
fn as_ref(&self) -> &(dyn OrgExampleTest + 'static) { &**self }
}
let myRc = Rc::new(myStruct);
myInterface = orgexampletest_server(&myFactory, (), move |_| myRc.clone());
还有一个 methodtype
参数,用于控制服务器函数是否与 MTFn
、MTFnMut
或 MTSync
树一起正常工作,或者三者都工作(称为 Generic
)。或者根本不生成服务器函数(None
)。
- 要发出信号,您可以调用
SignalArgs::to_emit_message
或ConnPath::emit
以获取可以发送到连接的消息。
用法
此代码既可以作为库使用,也可以作为二进制可执行文件。
二进制可执行文件
一旦安装了 dbus-codegen-rust(cargo install dbus-codegen
),请使用以下命令导入您的 XML 文件
dbus-codegen-rust < mydefinition.xml
这将打印生成的 Rust 代码到 stdout,因此如果您想将其管道传输到另一个文件,可以这样做
dbus-codegen-rust < mydefinition.xml > mod.rs
Dbus-codegen-rust 还可以为您获取 xml 定义。以下是一个为 PolicyKit 生成客户端定义的示例
dbus-codegen-rust -s -d org.freedesktop.PolicyKit1 -p "/org/freedesktop/PolicyKit1/Authority" > policykit.rs
Dbus-codegen-rust 默认生成客户端定义。使用 --crossroads
开关生成 dbus-crossroads 服务器定义,并使用 --methodtype
生成 dbus-tree 定义。
要查看可用选项
dbus-codegen-rust --help
库使用
let opts = Default::default();
let code = dbus_codegen::generate(xml_str, &opts)?;
有关可用选项的说明,请参阅文档。
功能
dbus
功能默认启用。如果您将其关闭(通过 cargo 的 --no-default-features
参数),则此程序(或库)不再绑定到 D-Bus C 开发头文件,这意味着您不需要安装这些文件。这也意味着您在运行二进制文件时无法从其他程序获取 xml 定义。
依赖项
~6MB
~127K SLoC