diff --git a/README.md b/README.md index 3b05b1c7..9256a15d 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ $ lua5.4 -e 'require("my_module").hello("world")' hello, world! ``` -On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content: +On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config.toml` with the following content: ``` toml [target.x86_64-apple-darwin] rustflags = [ diff --git a/src/state.rs b/src/state.rs index c8ba1f5f..35397ff5 100644 --- a/src/state.rs +++ b/src/state.rs @@ -271,7 +271,7 @@ impl Lua { #[inline] pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua { Lua { - raw: RawLua::init_from_ptr(state), + raw: RawLua::init_from_ptr(state, false), collect_garbage: true, } } diff --git a/src/state/extra.rs b/src/state/extra.rs index 3c04f077..5b2f8c08 100644 --- a/src/state/extra.rs +++ b/src/state/extra.rs @@ -33,6 +33,7 @@ const REF_STACK_RESERVE: c_int = 1; pub(crate) struct ExtraData { pub(super) lua: MaybeUninit, pub(super) weak: MaybeUninit, + pub(super) owned: bool, pub(super) registered_userdata: FxHashMap, pub(super) registered_userdata_mt: FxHashMap<*const c_void, Option>, @@ -46,7 +47,7 @@ pub(crate) struct ExtraData { pub(super) safe: bool, pub(super) libs: StdLib, - #[cfg(feature = "module")] + // Used in module mode pub(super) skip_memory_check: bool, // Auxiliary thread to store references @@ -88,8 +89,9 @@ pub(crate) struct ExtraData { impl Drop for ExtraData { fn drop(&mut self) { unsafe { - #[cfg(feature = "module")] - self.lua.assume_init_drop(); + if !self.owned { + self.lua.assume_init_drop(); + } self.weak.assume_init_drop(); } @@ -111,7 +113,7 @@ impl ExtraData { #[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))] pub(super) const ERROR_TRACEBACK_IDX: c_int = 1; - pub(super) unsafe fn init(state: *mut ffi::lua_State) -> XRc> { + pub(super) unsafe fn init(state: *mut ffi::lua_State, owned: bool) -> XRc> { // Create ref stack thread and place it in the registry to prevent it // from being garbage collected. let ref_thread = mlua_expect!( @@ -141,6 +143,7 @@ impl ExtraData { let extra = XRc::new(UnsafeCell::new(ExtraData { lua: MaybeUninit::uninit(), weak: MaybeUninit::uninit(), + owned, registered_userdata: FxHashMap::default(), registered_userdata_mt: FxHashMap::default(), last_checked_userdata_mt: (ptr::null(), None), @@ -148,7 +151,6 @@ impl ExtraData { app_data: AppData::default(), safe: false, libs: StdLib::NONE, - #[cfg(feature = "module")] skip_memory_check: false, ref_thread, // We need some reserved stack space to move values in and out of the ref stack. @@ -188,7 +190,7 @@ impl ExtraData { raw: XRc::clone(raw), collect_garbage: false, }); - if cfg!(not(feature = "module")) { + if self.owned { XRc::decrement_strong_count(XRc::as_ptr(raw)); } self.weak.write(WeakLua(XRc::downgrade(raw))); diff --git a/src/state/raw.rs b/src/state/raw.rs index ab056428..98f47956 100644 --- a/src/state/raw.rs +++ b/src/state/raw.rs @@ -50,10 +50,13 @@ pub struct RawLua { pub(super) extra: XRc>, } -#[cfg(not(feature = "module"))] impl Drop for RawLua { fn drop(&mut self) { unsafe { + if !(*self.extra.get()).owned { + return; + } + let mem_state = MemoryState::get(self.main_state); ffi::lua_close(self.main_state); @@ -115,7 +118,7 @@ impl RawLua { ffi::luau_codegen_create(state); } - let rawlua = Self::init_from_ptr(state); + let rawlua = Self::init_from_ptr(state, true); let extra = rawlua.lock().extra.get(); mlua_expect!( @@ -154,7 +157,7 @@ impl RawLua { rawlua } - pub(super) unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> XRc> { + pub(super) unsafe fn init_from_ptr(state: *mut ffi::lua_State, owned: bool) -> XRc> { assert!(!state.is_null(), "Lua state is NULL"); if let Some(lua) = Self::try_from_ptr(state) { return lua; @@ -191,7 +194,7 @@ impl RawLua { ); // Init ExtraData - let extra = ExtraData::init(main_state); + let extra = ExtraData::init(main_state, owned); // Register `DestructedUserdata` type get_destructed_userdata_metatable(main_state); @@ -704,10 +707,7 @@ impl RawLua { // MemoryInfo is empty in module mode so we cannot predict memory limits match MemoryState::get(self.main_state) { mem_state if !mem_state.is_null() => (*mem_state).memory_limit() == 0, - #[cfg(feature = "module")] _ => (*self.extra.get()).skip_memory_check, // Check the special flag (only for module mode) - #[cfg(not(feature = "module"))] - _ => false, } } diff --git a/tests/function.rs b/tests/function.rs index 2735e655..82c05fe0 100644 --- a/tests/function.rs +++ b/tests/function.rs @@ -84,8 +84,8 @@ fn test_c_function() -> Result<()> { let lua = Lua::new(); unsafe extern "C-unwind" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int { - let lua = Lua::init_from_ptr(state); - lua.globals().set("c_function", true).unwrap(); + ffi::lua_pushboolean(state, 1); + ffi::lua_setglobal(state, b"c_function\0" as *const _ as *const _); 0 } diff --git a/tests/module/loader/.cargo/config b/tests/module/loader/.cargo/config.toml similarity index 100% rename from tests/module/loader/.cargo/config rename to tests/module/loader/.cargo/config.toml diff --git a/tests/module/loader/tests/load.rs b/tests/module/loader/tests/load.rs index 8c4a5957..08473b99 100644 --- a/tests/module/loader/tests/load.rs +++ b/tests/module/loader/tests/load.rs @@ -92,6 +92,18 @@ fn test_module_multi_from_thread() -> Result<()> { .exec() } +#[test] +fn test_module_new_vm() -> Result<()> { + let lua = make_lua()?; + lua.load( + r#" + local mod = require("test_module.new_vm") + assert(mod.eval("return \"hello, world\"") == "hello, world") + "#, + ) + .exec() +} + fn make_lua() -> Result { let (dylib_path, dylib_ext, separator); if cfg!(target_os = "macos") { diff --git a/tests/module/src/lib.rs b/tests/module/src/lib.rs index 25689fe8..ac505824 100644 --- a/tests/module/src/lib.rs +++ b/tests/module/src/lib.rs @@ -33,6 +33,18 @@ fn test_module2(lua: &Lua) -> LuaResult { Ok(exports) } +#[mlua::lua_module] +fn test_module_new_vm(lua: &Lua) -> LuaResult { + let eval = lua.create_function(|_, prog: String| { + let lua = Lua::new(); + lua.load(prog).eval::>() + })?; + + let exports = lua.create_table()?; + exports.set("eval", eval)?; + Ok(exports) +} + #[mlua::lua_module] fn test_module_error(_: &Lua) -> LuaResult { Err("custom module error".into_lua_err())