Sure, sorry. I dropped details over in the thread in the rust forums.
The problem was the lifetimes. I needed to replace any datatype that requires a lifetime, with the equivalent datatype that doesn’t (e.g. &str
→ String
, and &[&str]
→ Vec<String>
). I didn’t understand that lifetimes aren’t needed for what I’m doing. They’re only used at compile-time, so in my situation it doesn’t make sense to accept a lifetime parameter. For example, &str
requires a known length at compile-time, but my string values are dynamic length.
So instead of…
struct SlidingWindow<'a> {
map: HashMap<&'a str, Vec<Option<f32>>>,
labels: &'a [&'a str],
index: usize,
length: usize,
width: usize,
}
…we need to use…
struct SlidingWindow {
map: HashMap<String, Vec<Option<f32>>>,
labels: Vec<String>,
index: usize,
length: usize,
width: usize,
}
And one other helpful thing. I realized you can package probably any mutable data in this generic structure:
struct Container {
mutex: Mutex<MyStruct>,
}
rustler::init!(
"Elixir.MyNif",
[func1, func2],
load = |env: Env, _| {
rustler::resource!(Container, env);
true
}
);
So you put whatever you want into MyStruct
, and you wrap it up for elixir like this…
let my_new_struct = MyStruct { ... };
let mutex = Mutex::new(my_new_struct);
let container = Container { mutex };
Ok(ResourceArc::new(container))
…then you can receive the same thing back, lock the mutex, unpack it, and do whatever mutations you need.
#[rustler::nif]
fn print(arc: ResourceArc<Container>) {
arc.mutex.lock().unwrap().print();
}
I’m happy to say that I have everything working in my project, have a look at master
if you’re interested.