-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Help] When variant is a struct? #436
Comments
Does this help:
If not, could you be more specific of what "a struct of strings and array of structs" mean, preferably by a code example? |
Thanks for the help. That's what I attempted to do but it didn't work. Here are the details: From this Go code, this is the struct that's sent over DBus. It has strings and array of structs, and HashMap (I forgot to mention this one in the question). So, I did something similar in Rust: pub struct Component {
pub name: String,
pub attachments: HashMap<String, arg::Variant<Box<dyn arg::RefArg>>>,
pub description: String,
pub version: String,
pub license: String,
pub author: String,
pub homepage: String,
pub exec: String,
pub textdomain: String,
pub engines: [EngineDesc; 1],
}
pub struct EngineDesc {
pub attachments: HashMap<String, arg::Variant<Box<dyn arg::RefArg>>>,
pub name: String,
pub longname: String,
pub description: String,
pub language: String,
pub license: String,
pub author: String,
pub icon: String,
pub layout: String,
pub rank: u32,
pub hotkeys: String,
pub symbol: String,
pub setup: String,
pub layout_variant: String,
pub layout_option: String,
pub version: String,
pub text_domain: String,
} Then I did what you suggested: let component = Component {
name: "org.freedesktop.IBus.Fcpinyin".to_owned(),
description: "Full Cloud Pinyin".to_owned(),
version: "0.1".to_owned(),
license: "MIT".to_owned(),
author: "Qingxiang Jia".to_owned(),
homepage: "https://github.com/qingxiang-jia/full-cloud-pinyin/".to_owned(),
exec: "".to_owned(),
textdomain: "full-cloud-pinyin".to_owned(),
attachments: HashMap::new(),
engines: [EngineDesc {
attachments: HashMap::new(),
name: "full-cloud-pinyin".to_owned(),
longname: "Full Cloud Pinyin".to_owned(),
description: "Full Cloud Pinyin".to_owned(),
language: "en".to_owned(),
license: "MIT".to_owned(),
author: "Qingxiang Jia".to_owned(),
icon: "/usr/share/icons/breeze/emblems/24@3x/emblem-checked.svg".to_owned(),
layout: "us".to_owned(),
rank: 0,
hotkeys: "".to_owned(),
symbol: "".to_owned(),
setup: "".to_owned(),
layout_option: "".to_owned(),
layout_variant: "".to_owned(),
version: "0.1".to_owned(),
text_domain: "full-cloud-pinyin".to_owned(),
}]
};
let componnet_variant = Box::new(component) as Box<dyn RefArg>;
match ibus.register_component(componnet_variant) {
Ok(()) => println!("Component registration successful!"),
Err(e) => {
println!("Failed to register component.");
display_debus_error(&e);
},
} I got: error[E0277]: the trait bound `manual::Component: RefArg` is not satisfied
--> src/main.rs:73:29
|
73 | let componnet_variant = Box::new(component) as Box<dyn RefArg>;
| ^^^^^^^^^^^^^^^^^^^ the trait `RefArg` is not implemented for `manual::Component`
|
= help: the following other types implement trait `RefArg`:
&'a T
&'a [T]
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
(A, B, C, D, E, F, G)
and 32 others
= note: required for the cast from `manual::Component` to the object type `dyn RefArg` So I was wondering if it's not supported to have a struct behind a variant. I am also wondering if I need to implement The source code of the above is here: qingxiang-jia/full-cloud-pinyin@9a2728a |
Right, so then you would do like this:
...or like this, if the first version does not work for some reason:
implementing RefArg for your struct works too, but the above is probably a lot easier. |
Thanks! Let me try it when I get home. |
Again, thanks for the help. But there's a few things I know I didn't get right (I think it's more about IBus, so maybe I should ask them than dbus-rs). I did your first suggested approach, basically putting the values into a tuple. There are some minor issues but in the end, the code compiles! However, the other end complained that I didn't pass in the right type (which is absolutely funny since they (IBus) defined it as a variant). The actual error message is (again, it's more about IBus than dbus-rs):
My guess is, with both approaches, we are passing in only the value, but not the "key". Here is what an IBusComponent should look like. Minor: I mentioned there was a minor issue, that is, when passing the tuple, the compiler complained that the "array of EngineDesc" doesn't implement RefArg. Omitting that solves the problem. The entire relevant code looks like the following: |
Yeah, I think at this point we need either better docs from IBus, or a working example in another language that we could translate to dbus-rs. Could be that they're not expecting a struct but a PropMap, like:
|
That's possible. The example from the other language is from Go: https://github.com/sarim/goibus/blob/eb16b0161e3b2289ca6e2b8eb6beb3997e86920f/ibus/component.go#L10 Let me try that and if it doesn't, I will still close this issue. If I ever get some updates from IBus, I will update the closed issue. |
Hi I did some exploration and I now have the exact signature of the variant I should send. It needs to be a variant of type I was following the tuple approach but it doesn't work because let attachments: HashMap<String, Box<dyn RefArg>> = HashMap::new();
let mut v: VecDeque<Box<dyn RefArg>> = VecDeque::new();
v.push_back(Box::new("org.freedesktop.IBus.Fcpinyin".to_owned()));
v.push_back(Box::new(attachments));
... But the compiler complains:
When returning, I got another issue with:
In case it helps, the full code is here. Thank you for the help! |
The following worked for me: The function in question attempts to return: Box<dyn RefArg> Later I will wrap it into dbus::arg::Variant(Box::new(thing)) // thing is what the function returned. Doing this gives me the second error in last post. The solution is to just wrap it into For the first error in the last post, the solution is to instead of declare The full code is: fn gen_engine_desc() -> dbus::arg::Variant<Box<dyn RefArg>> {
let attachments: HashMap<String, Variant<Box<dyn RefArg>>> = HashMap::new();
let mut v: VecDeque<Box<dyn RefArg>> = VecDeque::new();
v.push_back(Box::new("IBusEngineDesc".to_owned()));
v.push_back(Box::new(attachments));
...
v.push_back(Box::new("full-cloud-pinyin".to_owned()));
return dbus::arg::Variant(Box::new(v));
} |
@qingxiang-jia Glad you could solve it. For |
I am trying to build an input method for IBus that uses DBus. It has a method:
The type is variant but really, it's a struct of strings and array of structs. I read the argument guide but it seems to me that struct is not supported (I mean, struct as a DBus type is supported but not when a struct is a variant). Is it true that to pass struct as variant, we just need to implement RefArg? The generated method signature for
RegisterComponent
is:Thanks!
The text was updated successfully, but these errors were encountered: