Dirty hack to get lua 5.1 main state

This commit is contained in:
Alex Orlenko 2020-05-27 01:15:59 +01:00
parent a9a4cf13f1
commit d5c22d989a
4 changed files with 141 additions and 3 deletions

120
src/ffi/internals51.rs Normal file
View File

@ -0,0 +1,120 @@
// The MIT License (MIT)
//
// Copyright (c) 2020 A. Orlenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
use std::os::raw::*;
use crate::ffi::{lua_Alloc, lua_CFunction, lua_Hook, lua_Number, lua_State};
#[repr(C)]
struct lua_StateExt {
next: *mut c_void,
tt: u8,
marked: u8,
status: u8,
top: *mut c_void,
base: *mut c_void,
l_G: *mut global_State,
ci: *mut c_void,
savedpc: *const c_void,
stack_last: *mut c_void,
stack: *mut c_void,
end_ci: *mut c_void,
base_ci: *mut c_void,
stacksize: c_int,
size_ci: c_int,
nCcalls: c_ushort,
baseCcalls: c_ushort,
hookmask: u8,
allowhook: u8,
basehookcount: c_int,
hookcount: c_int,
hook: Option<lua_Hook>,
l_gt: TValue,
env: TValue,
openupval: *mut c_void,
gclist: *mut c_void,
errorJmp: *mut c_void,
errfunc: isize,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct TValue {
value: Value,
tt: c_int,
}
#[repr(C)]
#[derive(Clone, Copy)]
union Value {
gc: *mut c_void,
p: *mut c_void,
n: lua_Number,
b: c_int,
}
#[repr(C)]
struct global_State {
strt: stringtable,
frealloc: Option<lua_Alloc>,
ud: *mut c_void,
currentwhite: u8,
gcstate: u8,
sweepstrgc: c_int,
rootgc: *mut c_void,
sweepgc: *mut c_void,
gray: *mut c_void,
grayagain: *mut c_void,
weak: *mut c_void,
tmudata: *mut c_void,
buff: Mbuffer,
GCthreshold: usize,
totalbytes: usize,
estimate: usize,
gcdept: usize,
gcpause: c_int,
gcstepmul: c_int,
panic: Option<lua_CFunction>,
l_registry: TValue,
mainthread: *mut lua_State,
// Other fields ommited
}
#[repr(C)]
struct stringtable {
hash: *mut c_void,
nuse: c_uint,
size: c_int,
}
#[repr(C)]
struct Mbuffer {
buffer: *mut c_char,
n: usize,
buffsize: usize,
}
pub unsafe fn lua_getmainstate(state: *mut lua_State) -> *mut lua_State {
let state = state as *mut lua_StateExt;
let global = (*state).l_G;
(*global).mainthread
}

View File

@ -170,6 +170,9 @@ pub use self::lua::{lua_isyieldable, lua_version};
#[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))] #[cfg(any(feature = "lua54", feature = "lua53", feature = "lua52"))]
pub use self::lua::{lua_callk, lua_pcallk, lua_upvalueid, lua_upvaluejoin, lua_yieldk}; pub use self::lua::{lua_callk, lua_pcallk, lua_upvalueid, lua_upvaluejoin, lua_yieldk};
#[cfg(feature = "lua51")]
pub use self::internals51::lua_getmainstate;
// auxiliary library types // auxiliary library types
pub use self::lauxlib::luaL_Reg; pub use self::lauxlib::luaL_Reg;
@ -284,6 +287,9 @@ mod glue {
#[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))] #[cfg(any(feature = "lua52", feature = "lua51", feature = "luajit"))]
mod compat53; mod compat53;
#[cfg(feature = "lua51")]
mod internals51;
mod lauxlib; mod lauxlib;
mod lua; mod lua;
mod luaconf; mod luaconf;

View File

@ -279,7 +279,7 @@ impl Lua {
#[allow(clippy::missing_safety_doc)] #[allow(clippy::missing_safety_doc)]
pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua { pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
let main_state = get_main_state(state); let main_state = get_main_state(state);
let main_state_top = ffi::lua_gettop(state); let main_state_top = ffi::lua_gettop(main_state);
let ref_thread = mlua_expect!( let ref_thread = mlua_expect!(
protect_lua_closure(main_state, 0, 0, |state| { protect_lua_closure(main_state, 0, 0, |state| {
@ -324,7 +324,7 @@ impl Lua {
})); }));
mlua_expect!( mlua_expect!(
push_gc_userdata(state, Arc::downgrade(&extra)), push_gc_userdata(main_state, Arc::downgrade(&extra)),
"Error while storing extra data", "Error while storing extra data",
); );
mlua_expect!( mlua_expect!(

View File

@ -493,7 +493,19 @@ pub unsafe fn get_main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State
ffi::lua_pop(state, 1); ffi::lua_pop(state, 1);
main_state main_state
} }
#[cfg(any(feature = "lua51", feature = "luajit"))] #[cfg(feature = "lua51")]
{
// Check the current state first
let is_main_state = ffi::lua_pushthread(state) == 1;
ffi::lua_pop(state, 1);
if is_main_state {
state
} else {
// The function below is a dirty hack and uses Lua private internals
ffi::lua_getmainstate(state)
}
}
#[cfg(feature = "luajit")]
state state
} }