-
use clap::{load_yaml, App, ArgMatches};
use yaml_rust::yaml::Yaml;
struct Prueba<'a> {
yaml: &'a Yaml,
matches: ArgMatches<'a>,
}
impl<'a> Prueba<'a> {
pub fn new() -> Self {
let yaml: &'a Yaml = load_yaml!("cliopts.yml");
let matches = App::from_yaml(yaml).get_matches();
Prueba { yaml, matches }
}
}
fn main() {
let prueba = Prueba::new();
} I'm trying to make a wrapper for the from_yaml method but I cannot compile it. I must say I'm a rust noob, and maybe I'm asking something basic, but, after more than 1 day trying to make it compile I'm out of ideas of what is wrong here and I'm wondering if it's possible to do what I'm trying to do. Thanks in advance |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The problem you're running into is two-fold and related to Rust and memory, not necessarily The first and more simple problem is you're trying to store and return a pointer to memory that is immediately deallocated (don't live long enough). Here is the equivalent, but simplified version of what you're doing: struct Prueba<'a> {
s: &'a str, // <-- A reference to some memory in a "String"
}
impl<'a> Prueba<'a> {
fn new() -> Self {
let my_string = String::new("Memory"); // <-- Memory is allocated here and owned by "my_string"
Prueba { s: &my_string } // <-- Prueba has a reference to to the memory owned by "my_string"
} // <-- "my_string" is de-allocated. What does Prueba.s reference (point to) now???
} The memory referenced by both The fix is to store the owned memory somewhere, ideally inside Now that brings up the second problem. If we have the "owned" memory This sounds like it'd be no issue! But alas it's a major problem in computer science in general. This is because if struct field A has owned memory, meaning that memory has an address and struct field B points the address of field A all is good at first....but then the struct gets moved in memory some how (many things can cause this behind the scenes), now struct field A has a different address, and struct field B is still pointing to the old address of field A which is now invalid! Of course, it sounds like it should be easy, and Rust should be able to just update struct field B with the new address of field A since it's the one doing the moving, right? It's just not that simple, and isn't actually possible to do that. Rust has come up with some solutions this, naming So back to your problem! What you can do is make it so that anything in your For us that means we load the Unfortunately, just because of the API of the Also, we don't need to use The full working solution is: use clap::{App, ArgMatches, YamlLoader};
use yaml_rust::yaml::Yaml;
use lazy_static::lazy_static;
lazy_static! {
static ref YAML: Yaml =
YamlLoader::load_from_str(include_str!("cliopts.yml")).unwrap()[0].clone();
}
struct Prueba {
m: ArgMatches<'static>,
}
impl Prueba {
pub fn new() -> Self {
let m = App::from_yaml(&YAML).get_matches();
Prueba { m }
}
}
fn main() {
let prueba = Prueba::new();
} |
Beta Was this translation helpful? Give feedback.
The problem you're running into is two-fold and related to Rust and memory, not necessarily
clap
.The first and more simple problem is you're trying to store and return a pointer to memory that is immediately deallocated (don't live long enough).
Here is the equivalent, but simplified version of what you're doing: