Allow multiple entrypoints in a single module share the same Lua state.

Previously it would initialize different Lua instances.
Fixes #49.
This commit is contained in:
Alex Orlenko 2021-05-18 20:07:34 +01:00
parent 973b5c3bf5
commit e8de2a458a
4 changed files with 43 additions and 7 deletions

View File

@ -8,10 +8,27 @@ fn used_memory(lua: &Lua, _: ()) -> LuaResult<usize> {
Ok(lua.used_memory())
}
fn check_userdata(_: &Lua, ud: MyUserData) -> LuaResult<i32> {
Ok(ud.0)
}
#[mlua::lua_module]
fn rust_module(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;
exports.set("sum", lua.create_function(sum)?)?;
exports.set("used_memory", lua.create_function(used_memory)?)?;
exports.set("check_userdata", lua.create_function(check_userdata)?)?;
Ok(exports)
}
#[derive(Clone, Copy)]
struct MyUserData(i32);
impl LuaUserData for MyUserData {}
#[mlua::lua_module]
fn rust_module_second(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;
exports.set("userdata", lua.create_userdata(MyUserData(123))?)?;
Ok(exports)
}

View File

@ -174,7 +174,7 @@ pub unsafe extern "C" fn mlua_hook_proc(state: *mut lua_State, ar: *mut lua_Debu
_phantom: PhantomData,
};
let lua = Lua::make_from_ptr(state);
let lua = mlua_expect!(Lua::make_from_ptr(state), "cannot make Lua instance");
let hook_cb = mlua_expect!(lua.hook_callback(), "no hook callback set in hook_proc");
#[allow(clippy::match_wild_err_arm)]

View File

@ -369,6 +369,10 @@ impl Lua {
let main_state = maybe_main_state.unwrap_or(state);
let main_state_top = ffi::lua_gettop(main_state);
if let Some(lua) = Lua::make_from_ptr(state) {
return lua;
}
let ref_thread = mlua_expect!(
(|state| {
// Before initializing the error registry, we must set Error/Panic size.
@ -437,8 +441,8 @@ impl Lua {
);
let extra_key = &EXTRA_REGISTRY_KEY as *const u8 as *const c_void;
mlua_expect!(
ffi::safe::lua_rawsetp(main_state, ffi::LUA_REGISTRYINDEX, extra_key,),
"Error while storing extra data"
ffi::safe::lua_rawsetp(main_state, ffi::LUA_REGISTRYINDEX, extra_key),
"Error while storing extra data",
);
mlua_debug_assert!(
@ -1972,12 +1976,14 @@ impl Lua {
Ok(())
}
pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Self {
pub(crate) unsafe fn make_from_ptr(state: *mut ffi::lua_State) -> Option<Self> {
let _sg = StackGuard::new(state);
assert_stack(state, 1);
let extra_key = &EXTRA_REGISTRY_KEY as *const u8 as *const c_void;
ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, extra_key);
if ffi::lua_rawgetp(state, ffi::LUA_REGISTRYINDEX, extra_key) != ffi::LUA_TUSERDATA {
return None;
}
let extra = mlua_expect!(
(*get_gc_userdata::<Weak<Mutex<ExtraData>>>(state, -1)).upgrade(),
"extra is destroyed"
@ -1986,14 +1992,14 @@ impl Lua {
let safe = mlua_expect!(extra.lock(), "extra is poisoned").safe;
Lua {
Some(Lua {
state,
main_state: get_main_state(state),
extra,
ephemeral: true,
safe,
_no_ref_unwind_safe: PhantomData,
}
})
}
pub(crate) unsafe fn hook_callback(&self) -> Option<HookCallback> {

View File

@ -15,6 +15,19 @@ fn test_module() -> Result<()> {
.exec()
}
#[test]
fn test_module_multi() -> Result<()> {
let lua = make_lua()?;
lua.load(
r#"
local mod = require("rust_module")
local mod2 = require("rust_module.second")
assert(mod.check_userdata(mod2.userdata) == 123)
"#,
)
.exec()
}
#[cfg(any(
feature = "lua54",
feature = "lua53",