G'day all! I'm working on scripting integration with mlua, and am trying to figure out how to pass a mutable reference to some context that a scripting function needs, without being able to pass it directly in.
That is, I have some initialisation code:
globals.set(
"spawn",
lua.create_function(|_, (object, position): (mlua::Value, mlua::Value)| {
let ctx: &mut Context = /* obtain from somewhere, noting that this is a closure that I can move state into */;
spawn(ctx, object, position);
Ok(())
})?,
)?;
and at a later stage, I have
let ctx: &mut Context = /* obtained from outer scope */;
run_scripts(); // no way to pass ctx in here
where run_scripts will call the previously defined spawn (indirectly), all within the same thread, without violating any guarantees about mutable aliasing.
Is there a nice not-unsafe way to "smuggle" the state into the function for the duration of that scope? Something like:
let ctx: &mut Context = /* obtained from outer scope */;
*some_shared_state = Some(ctx);
run_scripts(); // no way to pass ctx in here
*some_shared_state = None;
and
lua.create_function(move |_, (object, position): (mlua::Value, mlua::Value)| {
let ctx: &mut Context = some_shared_state.unwrap();
spawn(ctx, object, position);
Ok(())
})?,
The naive solution of having a Arc<Mutex<Option<&mut Context>>> doesn't work, because then I have to specify lifetimes all the way up to the root of the program. Ideally, I want to be able to express "I am lending you access to this mutable borrow for this scope", and have some code elsewhere rely on that (with a failure at runtime being fine, because it should never fail).
Appreciate any thoughts!