使用 Rust DBUS 库时,不满足 trait bound `dbus::arg::Get`
Posted
技术标签:
【中文标题】使用 Rust DBUS 库时,不满足 trait bound `dbus::arg::Get`【英文标题】:The trait bound `dbus::arg::Get` is not satisfied when using the Rust DBUS library 【发布时间】:2017-05-17 12:00:07 【问题描述】:我正在尝试使用 the dbus-rs 库通过 GetSettings
方法从 NetworkManager 获取连接信息。我用D-Feet试了一下签名为GetSettings() -> (Dict of String, Dict of String, Variant settings)
的函数,D-Feet返回的数据如下:
'802-11-wireless': 'mac-address': [228, 179, 24, 77, 64, 139],
'mac-address-blacklist': [],
'mode': 'infrastructure',
'security': '802-11-wireless-security',
'seen-bssids': ['02:1D:AA:80:1B:DA', '02:1D:AA:80:1D:12'],
'ssid': [80,
108,
111,
117,
103,
104,
32,
87,
97,
121,
32,
67,
97,
102,
101],
'802-11-wireless-security': 'auth-alg': 'open',
'group': [],
'key-mgmt': 'wpa-psk',
'pairwise': [],
'proto': [],
'connection': 'id': 'Plough Way Cafe',
'permissions': [],
'secondaries': [],
'timestamp': 1479304123,
'type': '802-11-wireless',
'uuid': 'ff9b7028-0911-491a-bfe8-53cba76069da',
'ipv4': 'address-data': [],
'addresses': [],
'dns': [],
'dns-search': [],
'method': 'auto',
'route-data': [],
'routes': [],
'ipv6': 'address-data': [],
'addresses': [],
'dns': [],
'dns-search': [],
'method': 'auto',
'route-data': [],
'routes': []
和我的代码:
extern crate dbus;
fn main()
let message = dbus::Message::new_method_call("org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager/Settings/0",
"org.freedesktop.NetworkManager.Settings.\
Connection",
"GetSettings")
.unwrap();
let response = dbus::Connection::get_private(dbus::BusType::System)
.unwrap()
.send_with_reply_and_block(message, 2000)
.unwrap();
println!(":?", response);
let test: dbus::arg::Dict<&str, dbus::arg::Dict<&str, dbus::arg::Variant<()>, _>, _> =
response.get1().unwrap();
println!(":?", test);
导致此错误:
error[E0277]: the trait bound `(): dbus::arg::Get<'_>` is not satisfied
--> src/main.rs:20:18
|
20 | response.get1().unwrap();
| ^^^^ the trait `dbus::arg::Get<'_>` is not implemented for `()`
|
= note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Variant<()>`
= note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Dict<'_, &str, dbus::arg::Variant<()>, dbus::arg::Iter<'_>>`
= note: required because of the requirements on the impl of `dbus::arg::Get<'_>` for `dbus::arg::Dict<'_, &str, dbus::arg::Dict<'_, &str, dbus::arg::Variant<()>, dbus::arg::Iter<'_>>, dbus::arg::Iter<'_>>`
如何获取连接信息?
我认为Variant
的全部意义在于它可以保存不同类型的数据?我做错了什么?
如果我用&str
替换Variant
类型()
,它会打印出Dict(Iter("Unknown?!", "Unknown?!", "Unknown?!", "Unknown?!", "Unknown?!"), PhantomData)
。 Unknown?!
的值是多少?
API for Dict
也表示
从迭代器创建一个新的
Dict
。追加时使用迭代器。
我应该如何/应该改用这个?我确实设法取得了一些进展,也许是天真?
我的代码现在看起来像这样:
extern crate dbus;
extern crate network_manager;
#[derive(Default, Debug)]
struct Connection
path: String,
id: String,
uuid: String,
ssid: String,
interface: String,
security: String,
psk: String, // Only used when creating a new connection
fn main()
let connection = Connection
path: "/org/freedesktop/NetworkManager/Settings/0".to_string(),
..Default::default()
;
let message = dbus::Message::new_method_call("org.freedesktop.NetworkManager",
connection.path.clone(),
"org.freedesktop.NetworkManager.Settings.\
Connection",
"GetSettings")
.unwrap();
let response = dbus::Connection::get_private(dbus::BusType::System)
.unwrap()
.send_with_reply_and_block(message, 2000)
.unwrap();
let mut outer_array_iter = response.iter_init().recurse(97).unwrap();
loop
let mut outer_dict_iter = outer_array_iter.recurse(101).unwrap();
outer_dict_iter.next();
let mut inner_array_iter = outer_dict_iter.recurse(97).unwrap();
loop
let mut inner_dict_iter = inner_array_iter.recurse(101).unwrap();
let key = inner_dict_iter.read::<&str>().unwrap();
match key
"id" =>
let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
println!("id :?", val);
"uuid" =>
let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
println!("uuid :?", val);
"ssid" =>
let val: dbus::arg::Variant<dbus::arg::Array<i32, _>> = inner_dict_iter.read()
.unwrap();
println!("ssid :?", val);
"type" =>
let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
println!("interface :?", val);
"security" =>
let val: dbus::arg::Variant<&str> = inner_dict_iter.read().unwrap();
println!("security :?", val);
_ => (),
if !(inner_array_iter.next())
break;
if !(outer_array_iter.next())
break;
println!(":?", connection);
打印出来:
id Variant("Plough Way Cafe")
uuid Variant("e078808e-626f-4be9-bbb4-5e48b1d626de")
interface Variant("802-11-wireless")
ssid Variant(Array(Iter("u8", "u8", "u8", "u8", "u8", "u8", "u8", "u8"), PhantomData))
security Variant("802-11-wireless-security")
Connection path: "/org/freedesktop/NetworkManager/Settings/0", id: "", uuid: "", ssid: "", interface: "", security: "", psk: ""
如何将数据从Variant
中取出并放入我的connection
结构中?有没有更好的方法来使用迭代器,因为这感觉很脆弱?
【问题讨论】:
你上面的函数中response
的类型是什么?因为编译器似乎暗示它是()
。
@MatthieuM。我添加了这一行let x: () = response;
,错误为expected (), found struct `dbus::Message`
。 response
是 dbus::Message
啊,我的错误,进一步挖掘,似乎Get
被递归应用,直到它到达Variant<()>
,这就是()
的来源。
我在用这行替换test
的赋值时编译它:let test: Array<&str, _> = response.get1().unwrap();
(从this code example 得到)。这有帮助吗?
啊,显然这会导致相同的打印输出:Array(Iter("Unknown?!", "Unknown?!", "Unknown?!", "Unknown?!"), PhantomData)
..
【参考方案1】:
这里是如何通过修改第一个示例来修复它:
let test: dbus::arg::Dict<&str, dbus::arg::Dict<&str, dbus::arg::Variant<dbus::arg::Iter>, _>, _> =
response.get1().unwrap();
for (k1, v1) in test
println!("outer key = :?", k1);
for (k2, v2) in v1
println!(" inner key = :?, inner type = :?, string value = :?", k2, v2, v2.0.clone().get::<&str>());
如果您在获取变体时不知道变体中的内容,则需要使用Variant<Iter>
。然后,您必须使用 get::<&str>(), get::<u32>()
等来检索变体中的实际值。
【讨论】:
以上是关于使用 Rust DBUS 库时,不满足 trait bound `dbus::arg::Get`的主要内容,如果未能解决你的问题,请参考以下文章
Rust-线程:使用Sync和Send trait的可扩展并发
Rust-线程:使用Sync和Send trait的可扩展并发