rustfmt changes
This commit is contained in:
parent
8440298e71
commit
0022057058
|
@ -80,8 +80,9 @@ fn examples() -> LuaResult<()> {
|
|||
// Heterogeneous Lists. This is one way to call a function with multiple
|
||||
// parameters:
|
||||
|
||||
print
|
||||
.call::<_, ()>(hlist!["hello", "again", "from", "rust"])?;
|
||||
print.call::<_, ()>(
|
||||
hlist!["hello", "again", "from", "rust"],
|
||||
)?;
|
||||
|
||||
// You can bind rust functions to lua as well
|
||||
|
||||
|
@ -106,16 +107,24 @@ fn examples() -> LuaResult<()> {
|
|||
|
||||
// You can also accept variadic arguments to rust functions
|
||||
let join = lua.create_function(|lua, args| {
|
||||
let strings = lua.unpack::<LuaVariadic<String>>(args)?.0;
|
||||
// (This is quadratic!, it's just an example!)
|
||||
lua.pack(strings.iter().fold("".to_owned(), |a, b| a + b))
|
||||
})?;
|
||||
let strings = lua.unpack::<LuaVariadic<String>>(args)?.0;
|
||||
// (This is quadratic!, it's just an example!)
|
||||
lua.pack(strings.iter().fold("".to_owned(), |a, b| a + b))
|
||||
})?;
|
||||
globals.set("join", join)?;
|
||||
|
||||
assert_eq!(lua.eval::<bool>(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#)?,
|
||||
true);
|
||||
assert_eq!(lua.eval::<bool>(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#)?,
|
||||
false);
|
||||
assert_eq!(
|
||||
lua.eval::<bool>(
|
||||
r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#,
|
||||
)?,
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
lua.eval::<bool>(
|
||||
r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#,
|
||||
)?,
|
||||
false
|
||||
);
|
||||
assert_eq!(lua.eval::<String>(r#"join("a", "b", "c")"#)?, "abc");
|
||||
|
||||
// You can create userdata with methods and metamethods defined on them.
|
||||
|
@ -145,8 +154,10 @@ fn examples() -> LuaResult<()> {
|
|||
})?;
|
||||
globals.set("vec2", vec2_constructor)?;
|
||||
|
||||
assert_eq!(lua.eval::<f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()")?,
|
||||
5.0);
|
||||
assert_eq!(
|
||||
lua.eval::<f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()")?,
|
||||
5.0
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ pub trait LuaExternalResult<T> {
|
|||
}
|
||||
|
||||
impl<T, E> LuaExternalResult<T> for Result<T, E>
|
||||
where E: 'static + Error + Send
|
||||
where
|
||||
E: 'static + Error + Send,
|
||||
{
|
||||
fn to_lua_err(self) -> LuaResult<T> {
|
||||
self.map_err(|e| LuaExternalError(Box::new(e)).into())
|
||||
|
|
72
src/ffi.rs
72
src/ffi.rs
|
@ -47,18 +47,21 @@ pub const LUA_TTHREAD: c_int = 8;
|
|||
|
||||
extern "C" {
|
||||
pub fn lua_close(state: *mut lua_State);
|
||||
pub fn lua_callk(state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
ctx: lua_KContext,
|
||||
k: Option<lua_KFunction>);
|
||||
pub fn lua_pcallk(state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
msgh: c_int,
|
||||
ctx: lua_KContext,
|
||||
k: Option<lua_KFunction>)
|
||||
-> c_int;
|
||||
pub fn lua_callk(
|
||||
state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
ctx: lua_KContext,
|
||||
k: Option<lua_KFunction>,
|
||||
);
|
||||
pub fn lua_pcallk(
|
||||
state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
msgh: c_int,
|
||||
ctx: lua_KContext,
|
||||
k: Option<lua_KFunction>,
|
||||
) -> c_int;
|
||||
pub fn lua_resume(state: *mut lua_State, from: *mut lua_State, nargs: c_int) -> c_int;
|
||||
pub fn lua_status(state: *mut lua_State) -> c_int;
|
||||
|
||||
|
@ -115,19 +118,22 @@ extern "C" {
|
|||
|
||||
pub fn luaL_newstate() -> *mut lua_State;
|
||||
pub fn luaL_openlibs(state: *mut lua_State);
|
||||
pub fn luaL_loadbufferx(state: *mut lua_State,
|
||||
buf: *const c_char,
|
||||
size: usize,
|
||||
name: *const c_char,
|
||||
mode: *const c_char)
|
||||
-> c_int;
|
||||
pub fn luaL_loadbufferx(
|
||||
state: *mut lua_State,
|
||||
buf: *const c_char,
|
||||
size: usize,
|
||||
name: *const c_char,
|
||||
mode: *const c_char,
|
||||
) -> c_int;
|
||||
pub fn luaL_ref(state: *mut lua_State, table: c_int) -> c_int;
|
||||
pub fn luaL_unref(state: *mut lua_State, table: c_int, lref: c_int);
|
||||
pub fn luaL_checkstack(state: *mut lua_State, size: c_int, msg: *const c_char);
|
||||
pub fn luaL_traceback(push_state: *mut lua_State,
|
||||
state: *mut lua_State,
|
||||
msg: *const c_char,
|
||||
level: c_int);
|
||||
pub fn luaL_traceback(
|
||||
push_state: *mut lua_State,
|
||||
state: *mut lua_State,
|
||||
msg: *const c_char,
|
||||
level: c_int,
|
||||
);
|
||||
pub fn luaL_len(push_state: *mut lua_State, index: c_int) -> lua_Integer;
|
||||
}
|
||||
|
||||
|
@ -228,11 +234,12 @@ pub unsafe fn lua_call(state: *mut lua_State, nargs: c_int, nresults: c_int) {
|
|||
lua_callk(state, nargs, nresults, ptr::null_mut(), None)
|
||||
}
|
||||
|
||||
pub unsafe fn lua_pcall(state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
msgh: c_int)
|
||||
-> c_int {
|
||||
pub unsafe fn lua_pcall(
|
||||
state: *mut lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
msgh: c_int,
|
||||
) -> c_int {
|
||||
lua_pcallk(state, nargs, nresults, msgh, ptr::null_mut(), None)
|
||||
}
|
||||
|
||||
|
@ -241,10 +248,11 @@ pub unsafe fn lua_replace(state: *mut lua_State, index: c_int) {
|
|||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
pub unsafe fn luaL_loadbuffer(state: *mut lua_State,
|
||||
buf: *const c_char,
|
||||
size: usize,
|
||||
name: *const c_char)
|
||||
-> c_int {
|
||||
pub unsafe fn luaL_loadbuffer(
|
||||
state: *mut lua_State,
|
||||
buf: *const c_char,
|
||||
size: usize,
|
||||
name: *const c_char,
|
||||
) -> c_int {
|
||||
luaL_loadbufferx(state, buf, size, name, ptr::null())
|
||||
}
|
||||
|
|
271
src/lua.rs
271
src/lua.rs
|
@ -88,8 +88,10 @@ pub trait FromLuaMulti<'a>: Sized {
|
|||
fn from_lua_multi(values: LuaMultiValue<'a>, lua: &'a Lua) -> LuaResult<Self>;
|
||||
}
|
||||
|
||||
type LuaCallback = Box<for<'lua> FnMut(&'lua Lua, LuaMultiValue<'lua>)
|
||||
-> LuaResult<LuaMultiValue<'lua>>>;
|
||||
type LuaCallback = Box<
|
||||
for<'lua> FnMut(&'lua Lua, LuaMultiValue<'lua>)
|
||||
-> LuaResult<LuaMultiValue<'lua>>,
|
||||
>;
|
||||
|
||||
struct LuaRef<'lua> {
|
||||
lua: &'lua Lua,
|
||||
|
@ -261,9 +263,10 @@ impl<'lua> LuaTable<'lua> {
|
|||
|
||||
/// Loop over each key, value pair in the table
|
||||
pub fn for_each_pair<K, V, F>(&self, mut f: F) -> LuaResult<()>
|
||||
where K: FromLua<'lua>,
|
||||
V: FromLua<'lua>,
|
||||
F: FnMut(K, V)
|
||||
where
|
||||
K: FromLua<'lua>,
|
||||
V: FromLua<'lua>,
|
||||
F: FnMut(K, V),
|
||||
{
|
||||
let lua = self.0.lua;
|
||||
unsafe {
|
||||
|
@ -358,8 +361,10 @@ impl<'lua> LuaFunction<'lua> {
|
|||
for arg in args {
|
||||
lua.push_value(lua.state, arg)?;
|
||||
}
|
||||
handle_error(lua.state,
|
||||
pcall_with_traceback(lua.state, nargs, ffi::LUA_MULTRET))?;
|
||||
handle_error(
|
||||
lua.state,
|
||||
pcall_with_traceback(lua.state, nargs, ffi::LUA_MULTRET),
|
||||
)?;
|
||||
let nresults = ffi::lua_gettop(lua.state) - stack_start;
|
||||
let mut results = LuaMultiValue::new();
|
||||
for _ in 0..nresults {
|
||||
|
@ -427,9 +432,10 @@ pub struct LuaThread<'lua>(LuaRef<'lua>);
|
|||
impl<'lua> LuaThread<'lua> {
|
||||
/// If this thread has yielded a value, will return Some, otherwise the thread is finished and
|
||||
/// this will return None.
|
||||
pub fn resume<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(&self,
|
||||
args: A)
|
||||
-> LuaResult<Option<R>> {
|
||||
pub fn resume<A: ToLuaMulti<'lua>, R: FromLuaMulti<'lua>>(
|
||||
&self,
|
||||
args: A,
|
||||
) -> LuaResult<Option<R>> {
|
||||
let lua = self.0.lua;
|
||||
unsafe {
|
||||
stack_guard(lua.state, 0, || {
|
||||
|
@ -447,8 +453,10 @@ impl<'lua> LuaThread<'lua> {
|
|||
lua.push_value(thread_state, arg)?;
|
||||
}
|
||||
|
||||
handle_error(lua.state,
|
||||
resume_with_traceback(thread_state, lua.state, nargs))?;
|
||||
handle_error(
|
||||
lua.state,
|
||||
resume_with_traceback(thread_state, lua.state, nargs),
|
||||
)?;
|
||||
|
||||
let nresults = ffi::lua_gettop(thread_state);
|
||||
let mut results = LuaMultiValue::new();
|
||||
|
@ -520,8 +528,10 @@ impl<T: LuaUserDataType> LuaUserDataMethods<T> {
|
|||
where M: 'static + for<'a, 'lua> FnMut(&'lua Lua, &'a T, LuaMultiValue<'lua>)
|
||||
-> LuaResult<LuaMultiValue<'lua>>
|
||||
{
|
||||
self.methods
|
||||
.insert(name.to_owned(), Self::box_method(method));
|
||||
self.methods.insert(
|
||||
name.to_owned(),
|
||||
Self::box_method(method),
|
||||
);
|
||||
}
|
||||
|
||||
/// Add a regular method as a function which accepts a &mut T parameter
|
||||
|
@ -529,8 +539,10 @@ impl<T: LuaUserDataType> LuaUserDataMethods<T> {
|
|||
where M: 'static + for<'a, 'lua> FnMut(&'lua Lua, &'a mut T, LuaMultiValue<'lua>)
|
||||
-> LuaResult<LuaMultiValue<'lua>>
|
||||
{
|
||||
self.methods
|
||||
.insert(name.to_owned(), Self::box_method_mut(method));
|
||||
self.methods.insert(
|
||||
name.to_owned(),
|
||||
Self::box_method_mut(method),
|
||||
);
|
||||
}
|
||||
|
||||
/// Add a regular method as a function which accepts generic arguments, the first argument will
|
||||
|
@ -572,12 +584,12 @@ impl<T: LuaUserDataType> LuaUserDataMethods<T> {
|
|||
-> LuaResult<LuaMultiValue<'lua>>
|
||||
{
|
||||
Box::new(move |lua, mut args| if let Some(front) = args.pop_front() {
|
||||
let userdata = LuaUserData::from_lua(front, lua)?;
|
||||
let userdata = userdata.borrow::<T>()?;
|
||||
method(lua, &userdata, args)
|
||||
} else {
|
||||
Err("No userdata supplied as first argument to method".into())
|
||||
})
|
||||
let userdata = LuaUserData::from_lua(front, lua)?;
|
||||
let userdata = userdata.borrow::<T>()?;
|
||||
method(lua, &userdata, args)
|
||||
} else {
|
||||
Err("No userdata supplied as first argument to method".into())
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
@ -586,12 +598,12 @@ impl<T: LuaUserDataType> LuaUserDataMethods<T> {
|
|||
-> LuaResult<LuaMultiValue<'lua>>
|
||||
{
|
||||
Box::new(move |lua, mut args| if let Some(front) = args.pop_front() {
|
||||
let userdata = LuaUserData::from_lua(front, lua)?;
|
||||
let mut userdata = userdata.borrow_mut::<T>()?;
|
||||
method(lua, &mut userdata, args)
|
||||
} else {
|
||||
Err("No userdata supplied as first argument to method".into())
|
||||
})
|
||||
let userdata = LuaUserData::from_lua(front, lua)?;
|
||||
let mut userdata = userdata.borrow_mut::<T>()?;
|
||||
method(lua, &mut userdata, args)
|
||||
} else {
|
||||
Err("No userdata supplied as first argument to method".into())
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -623,8 +635,9 @@ impl<'lua> LuaUserData<'lua> {
|
|||
}
|
||||
|
||||
fn inspect<'a, T, R, F>(&'a self, func: F) -> LuaResult<R>
|
||||
where T: LuaUserDataType,
|
||||
F: FnOnce(&'a RefCell<T>) -> LuaResult<R>
|
||||
where
|
||||
T: LuaUserDataType,
|
||||
F: FnOnce(&'a RefCell<T>) -> LuaResult<R>,
|
||||
{
|
||||
unsafe {
|
||||
let lua = self.0.lua;
|
||||
|
@ -641,9 +654,11 @@ impl<'lua> LuaUserData<'lua> {
|
|||
return Err("value has no metatable".into());
|
||||
}
|
||||
|
||||
ffi::lua_rawgeti(lua.state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
lua.userdata_metatable::<T>()? as ffi::lua_Integer);
|
||||
ffi::lua_rawgeti(
|
||||
lua.state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
lua.userdata_metatable::<T>()? as ffi::lua_Integer,
|
||||
);
|
||||
if ffi::lua_rawequal(lua.state, -1, -2) == 0 {
|
||||
return Err("wrong metatable type for lua userdata".into());
|
||||
}
|
||||
|
@ -681,13 +696,15 @@ impl Lua {
|
|||
ffi::luaL_openlibs(state);
|
||||
|
||||
stack_guard(state, 0, || {
|
||||
ffi::lua_pushlightuserdata(state,
|
||||
&LUA_USERDATA_REGISTRY_KEY as *const u8 as *mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
state,
|
||||
&LUA_USERDATA_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
|
||||
let registered_userdata =
|
||||
ffi::lua_newuserdata(state,
|
||||
mem::size_of::<RefCell<HashMap<TypeId, c_int>>>()) as
|
||||
*mut RefCell<HashMap<TypeId, c_int>>;
|
||||
let registered_userdata = ffi::lua_newuserdata(
|
||||
state,
|
||||
mem::size_of::<RefCell<HashMap<TypeId, c_int>>>(),
|
||||
) as *mut RefCell<HashMap<TypeId, c_int>>;
|
||||
ptr::write(registered_userdata, RefCell::new(HashMap::new()));
|
||||
|
||||
ffi::lua_newtable(state);
|
||||
|
@ -703,9 +720,10 @@ impl Lua {
|
|||
}).unwrap();
|
||||
|
||||
stack_guard(state, 0, || {
|
||||
ffi::lua_pushlightuserdata(state,
|
||||
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as
|
||||
*mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
state,
|
||||
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
|
||||
ffi::lua_newtable(state);
|
||||
|
||||
|
@ -744,30 +762,39 @@ impl Lua {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load<'lua, R: FromLuaMulti<'lua>>(&'lua self,
|
||||
source: &str,
|
||||
name: Option<&str>)
|
||||
-> LuaResult<R> {
|
||||
pub fn load<'lua, R: FromLuaMulti<'lua>>(
|
||||
&'lua self,
|
||||
source: &str,
|
||||
name: Option<&str>,
|
||||
) -> LuaResult<R> {
|
||||
unsafe {
|
||||
stack_guard(self.state, 0, || {
|
||||
let stack_start = ffi::lua_gettop(self.state);
|
||||
handle_error(self.state,
|
||||
if let Some(name) = name {
|
||||
let name = CString::new(name.to_owned())?;
|
||||
ffi::luaL_loadbuffer(self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
name.as_ptr())
|
||||
} else {
|
||||
ffi::luaL_loadbuffer(self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
ptr::null())
|
||||
})?;
|
||||
handle_error(
|
||||
self.state,
|
||||
if let Some(name) = name {
|
||||
let name = CString::new(name.to_owned())?;
|
||||
ffi::luaL_loadbuffer(
|
||||
self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
name.as_ptr(),
|
||||
)
|
||||
} else {
|
||||
ffi::luaL_loadbuffer(
|
||||
self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
ptr::null(),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
check_stack(self.state, 2)?;
|
||||
handle_error(self.state,
|
||||
pcall_with_traceback(self.state, 0, ffi::LUA_MULTRET))?;
|
||||
handle_error(
|
||||
self.state,
|
||||
pcall_with_traceback(self.state, 0, ffi::LUA_MULTRET),
|
||||
)?;
|
||||
|
||||
let nresults = ffi::lua_gettop(self.state) - stack_start;
|
||||
let mut results = LuaMultiValue::new();
|
||||
|
@ -789,23 +816,29 @@ impl Lua {
|
|||
// "return", then as a statement. This is the same thing the
|
||||
// actual lua repl does.
|
||||
let return_source = "return ".to_owned() + source;
|
||||
let mut res = ffi::luaL_loadbuffer(self.state,
|
||||
return_source.as_ptr() as *const c_char,
|
||||
return_source.len(),
|
||||
ptr::null());
|
||||
let mut res = ffi::luaL_loadbuffer(
|
||||
self.state,
|
||||
return_source.as_ptr() as *const c_char,
|
||||
return_source.len(),
|
||||
ptr::null(),
|
||||
);
|
||||
if res == ffi::LUA_ERRSYNTAX {
|
||||
ffi::lua_pop(self.state, 1);
|
||||
res = ffi::luaL_loadbuffer(self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
ptr::null());
|
||||
res = ffi::luaL_loadbuffer(
|
||||
self.state,
|
||||
source.as_ptr() as *const c_char,
|
||||
source.len(),
|
||||
ptr::null(),
|
||||
);
|
||||
}
|
||||
|
||||
handle_error(self.state, res)?;
|
||||
|
||||
check_stack(self.state, 2)?;
|
||||
handle_error(self.state,
|
||||
pcall_with_traceback(self.state, 0, ffi::LUA_MULTRET))?;
|
||||
handle_error(
|
||||
self.state,
|
||||
pcall_with_traceback(self.state, 0, ffi::LUA_MULTRET),
|
||||
)?;
|
||||
|
||||
let nresults = ffi::lua_gettop(self.state) - stack_start;
|
||||
let mut results = LuaMultiValue::new();
|
||||
|
@ -838,9 +871,10 @@ impl Lua {
|
|||
}
|
||||
|
||||
pub fn create_table<'lua, K, V, I>(&'lua self, cont: I) -> LuaResult<LuaTable>
|
||||
where K: ToLua<'lua>,
|
||||
V: ToLua<'lua>,
|
||||
I: IntoIterator<Item = (K, V)>
|
||||
where
|
||||
K: ToLua<'lua>,
|
||||
V: ToLua<'lua>,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
unsafe {
|
||||
stack_guard(self.state, 0, || {
|
||||
|
@ -858,14 +892,16 @@ impl Lua {
|
|||
}
|
||||
|
||||
pub fn create_array_table<'lua, T, I>(&'lua self, cont: I) -> LuaResult<LuaTable>
|
||||
where T: ToLua<'lua>,
|
||||
I: IntoIterator<Item = T>
|
||||
where
|
||||
T: ToLua<'lua>,
|
||||
I: IntoIterator<Item = T>,
|
||||
{
|
||||
self.create_table(cont.into_iter().enumerate().map(|(k, v)| (k + 1, v)))
|
||||
}
|
||||
|
||||
pub fn create_function<F>(&self, func: F) -> LuaResult<LuaFunction>
|
||||
where F: 'static + for<'a> FnMut(&'a Lua, LuaMultiValue<'a>) -> LuaResult<LuaMultiValue<'a>>
|
||||
where
|
||||
F: 'static + for<'a> FnMut(&'a Lua, LuaMultiValue<'a>) -> LuaResult<LuaMultiValue<'a>>,
|
||||
{
|
||||
self.create_callback_function(Box::new(func))
|
||||
}
|
||||
|
@ -884,21 +920,24 @@ impl Lua {
|
|||
}
|
||||
|
||||
pub fn create_userdata<T>(&self, data: T) -> LuaResult<LuaUserData>
|
||||
where T: LuaUserDataType
|
||||
where
|
||||
T: LuaUserDataType,
|
||||
{
|
||||
unsafe {
|
||||
stack_guard(self.state, 0, move || {
|
||||
check_stack(self.state, 2)?;
|
||||
|
||||
let data = RefCell::new(data);
|
||||
let data_userdata = ffi::lua_newuserdata(self.state,
|
||||
mem::size_of::<RefCell<T>>()) as
|
||||
*mut RefCell<T>;
|
||||
let data_userdata =
|
||||
ffi::lua_newuserdata(self.state, mem::size_of::<RefCell<T>>()) as
|
||||
*mut RefCell<T>;
|
||||
ptr::write(data_userdata, data);
|
||||
|
||||
ffi::lua_rawgeti(self.state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
self.userdata_metatable::<T>()? as ffi::lua_Integer);
|
||||
ffi::lua_rawgeti(
|
||||
self.state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
self.userdata_metatable::<T>()? as ffi::lua_Integer,
|
||||
);
|
||||
|
||||
ffi::lua_setmetatable(self.state, -2);
|
||||
|
||||
|
@ -987,9 +1026,10 @@ impl Lua {
|
|||
t.to_lua_multi(self)
|
||||
}
|
||||
|
||||
pub fn unpack<'lua, T: FromLuaMulti<'lua>>(&'lua self,
|
||||
value: LuaMultiValue<'lua>)
|
||||
-> LuaResult<T> {
|
||||
pub fn unpack<'lua, T: FromLuaMulti<'lua>>(
|
||||
&'lua self,
|
||||
value: LuaMultiValue<'lua>,
|
||||
) -> LuaResult<T> {
|
||||
T::from_lua_multi(value, self)
|
||||
}
|
||||
|
||||
|
@ -1003,7 +1043,7 @@ impl Lua {
|
|||
};
|
||||
|
||||
let func = &mut *(ffi::lua_touserdata(state, ffi::lua_upvalueindex(1)) as
|
||||
*mut LuaCallback);
|
||||
*mut LuaCallback);
|
||||
|
||||
let nargs = ffi::lua_gettop(state);
|
||||
let mut args = LuaMultiValue::new();
|
||||
|
@ -1026,14 +1066,15 @@ impl Lua {
|
|||
stack_guard(self.state, 0, move || {
|
||||
check_stack(self.state, 2)?;
|
||||
|
||||
let func_userdata = ffi::lua_newuserdata(self.state,
|
||||
mem::size_of::<LuaCallback>()) as
|
||||
*mut LuaCallback;
|
||||
let func_userdata =
|
||||
ffi::lua_newuserdata(self.state, mem::size_of::<LuaCallback>()) as
|
||||
*mut LuaCallback;
|
||||
ptr::write(func_userdata, func);
|
||||
|
||||
ffi::lua_pushlightuserdata(self.state,
|
||||
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as
|
||||
*mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
self.state,
|
||||
&FUNCTION_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
ffi::lua_gettable(self.state, ffi::LUA_REGISTRYINDEX);
|
||||
ffi::lua_setmetatable(self.state, -2);
|
||||
|
||||
|
@ -1137,13 +1178,17 @@ impl Lua {
|
|||
}
|
||||
|
||||
unsafe fn push_ref(&self, state: *mut ffi::lua_State, lref: &LuaRef) {
|
||||
assert_eq!(lref.lua.main_state,
|
||||
self.main_state,
|
||||
"Lua instance passed LuaValue created from a different Lua");
|
||||
assert_eq!(
|
||||
lref.lua.main_state,
|
||||
self.main_state,
|
||||
"Lua instance passed LuaValue created from a different Lua"
|
||||
);
|
||||
|
||||
ffi::lua_rawgeti(state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
lref.registry_id as ffi::lua_Integer);
|
||||
ffi::lua_rawgeti(
|
||||
state,
|
||||
ffi::LUA_REGISTRYINDEX,
|
||||
lref.registry_id as ffi::lua_Integer,
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn pop_ref(&self, state: *mut ffi::lua_State) -> LuaRef {
|
||||
|
@ -1176,11 +1221,13 @@ impl Lua {
|
|||
stack_guard(self.state, 0, move || {
|
||||
check_stack(self.state, 3)?;
|
||||
|
||||
ffi::lua_pushlightuserdata(self.state,
|
||||
&LUA_USERDATA_REGISTRY_KEY as *const u8 as *mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
self.state,
|
||||
&LUA_USERDATA_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
ffi::lua_gettable(self.state, ffi::LUA_REGISTRYINDEX);
|
||||
let registered_userdata = ffi::lua_touserdata(self.state, -1) as
|
||||
*mut RefCell<HashMap<TypeId, c_int>>;
|
||||
*mut RefCell<HashMap<TypeId, c_int>>;
|
||||
let mut map = (*registered_userdata).borrow_mut();
|
||||
ffi::lua_pop(self.state, 1);
|
||||
|
||||
|
@ -1205,8 +1252,10 @@ impl Lua {
|
|||
check_stack(self.state, methods.methods.len() as c_int * 2)?;
|
||||
for (k, m) in methods.methods {
|
||||
push_string(self.state, &k);
|
||||
self.push_value(self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?))?;
|
||||
self.push_value(
|
||||
self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?),
|
||||
)?;
|
||||
ffi::lua_rawset(self.state, -3);
|
||||
}
|
||||
|
||||
|
@ -1219,8 +1268,10 @@ impl Lua {
|
|||
push_string(self.state, "__index");
|
||||
ffi::lua_pushvalue(self.state, -1);
|
||||
ffi::lua_gettable(self.state, -3);
|
||||
self.push_value(self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?))?;
|
||||
self.push_value(
|
||||
self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?),
|
||||
)?;
|
||||
ffi::lua_pushcclosure(self.state, meta_index_impl, 2);
|
||||
ffi::lua_rawset(self.state, -3);
|
||||
} else {
|
||||
|
@ -1242,8 +1293,10 @@ impl Lua {
|
|||
LuaMetaMethod::Call => "__call",
|
||||
};
|
||||
push_string(self.state, name);
|
||||
self.push_value(self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?))?;
|
||||
self.push_value(
|
||||
self.state,
|
||||
LuaValue::Function(self.create_callback_function(m)?),
|
||||
)?;
|
||||
ffi::lua_rawset(self.state, -3);
|
||||
}
|
||||
}
|
||||
|
|
62
src/tests.rs
62
src/tests.rs
|
@ -41,12 +41,14 @@ fn test_load() {
|
|||
None,
|
||||
).unwrap();
|
||||
assert!(module.has("func").unwrap());
|
||||
assert_eq!(module
|
||||
.get::<_, LuaFunction>("func")
|
||||
.unwrap()
|
||||
.call::<_, String>(())
|
||||
.unwrap(),
|
||||
"hello");
|
||||
assert_eq!(
|
||||
module
|
||||
.get::<_, LuaFunction>("func")
|
||||
.unwrap()
|
||||
.call::<_, String>(())
|
||||
.unwrap(),
|
||||
"hello"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -92,22 +94,30 @@ fn test_table() {
|
|||
let table3 = globals.get::<_, LuaTable>("table3").unwrap();
|
||||
|
||||
assert_eq!(table1.length().unwrap(), 5);
|
||||
assert_eq!(table1.pairs::<i64, i64>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]);
|
||||
assert_eq!(
|
||||
table1.pairs::<i64, i64>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
assert_eq!(table2.length().unwrap(), 0);
|
||||
assert_eq!(table2.pairs::<i64, i64>().unwrap(), vec![]);
|
||||
assert_eq!(table2.array_values::<i64>().unwrap(), vec![]);
|
||||
assert_eq!(table3.length().unwrap(), 5);
|
||||
assert_eq!(table3.array_values::<Option<i64>>().unwrap(),
|
||||
vec![Some(1), Some(2), None, Some(4), Some(5)]);
|
||||
assert_eq!(
|
||||
table3.array_values::<Option<i64>>().unwrap(),
|
||||
vec![Some(1), Some(2), None, Some(4), Some(5)]
|
||||
);
|
||||
|
||||
globals
|
||||
.set("table4",
|
||||
lua.create_array_table(vec![1, 2, 3, 4, 5]).unwrap())
|
||||
.set(
|
||||
"table4",
|
||||
lua.create_array_table(vec![1, 2, 3, 4, 5]).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let table4 = globals.get::<_, LuaTable>("table4").unwrap();
|
||||
assert_eq!(table4.pairs::<i64, i64>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]);
|
||||
assert_eq!(
|
||||
table4.pairs::<i64, i64>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -124,8 +134,10 @@ fn test_function() {
|
|||
).unwrap();
|
||||
|
||||
let concat = globals.get::<_, LuaFunction>("concat").unwrap();
|
||||
assert_eq!(concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar");
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -149,8 +161,10 @@ fn test_bind() {
|
|||
concat = concat.bind("foo").unwrap();
|
||||
concat = concat.bind("bar").unwrap();
|
||||
concat = concat.bind(hlist!["baz", "baf"]).unwrap();
|
||||
assert_eq!(concat.call::<_, String>(hlist!["hi", "wut"]).unwrap(),
|
||||
"foobarbazbafhiwut");
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["hi", "wut"]).unwrap(),
|
||||
"foobarbazbafhiwut"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -331,8 +345,10 @@ fn test_lua_multi() {
|
|||
let concat = globals.get::<_, LuaFunction>("concat").unwrap();
|
||||
let mreturn = globals.get::<_, LuaFunction>("mreturn").unwrap();
|
||||
|
||||
assert_eq!(concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar");
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar"
|
||||
);
|
||||
let hlist_pat![a, b] = mreturn.call::<_, HList![u64, u64]>(hlist![]).unwrap();
|
||||
assert_eq!((a, b), (1, 2));
|
||||
let hlist_pat![a, b, LuaVariadic(v)] = mreturn.call::<_, HList![u64, u64, LuaVariadic<u64>]>(hlist![]).unwrap();
|
||||
|
@ -423,9 +439,9 @@ fn test_error() {
|
|||
None,
|
||||
).unwrap();
|
||||
|
||||
let rust_error_function =
|
||||
lua.create_function(|_, _| Err(LuaExternalError(Box::new(TestError)).into()))
|
||||
.unwrap();
|
||||
let rust_error_function = lua.create_function(
|
||||
|_, _| Err(LuaExternalError(Box::new(TestError)).into()),
|
||||
).unwrap();
|
||||
globals
|
||||
.set("rust_error_function", rust_error_function)
|
||||
.unwrap();
|
||||
|
|
141
src/util.rs
141
src/util.rs
|
@ -30,23 +30,30 @@ pub unsafe fn check_stack(state: *mut ffi::lua_State, amount: c_int) -> LuaResul
|
|||
// results in an error and the stack is smaller than the value before the call, then this is
|
||||
// unrecoverable and this will panic.
|
||||
pub unsafe fn stack_guard<F, R>(state: *mut ffi::lua_State, change: c_int, op: F) -> LuaResult<R>
|
||||
where F: FnOnce() -> LuaResult<R>
|
||||
where
|
||||
F: FnOnce() -> LuaResult<R>,
|
||||
{
|
||||
let expected = ffi::lua_gettop(state) + change;
|
||||
assert!(expected >= 0,
|
||||
"lua stack error, too many values would be popped");
|
||||
assert!(
|
||||
expected >= 0,
|
||||
"lua stack error, too many values would be popped"
|
||||
);
|
||||
let res = op();
|
||||
let top = ffi::lua_gettop(state);
|
||||
if res.is_ok() {
|
||||
assert_eq!(ffi::lua_gettop(state),
|
||||
expected,
|
||||
"lua stack error, expected stack to be {}, got {}",
|
||||
expected,
|
||||
top);
|
||||
assert_eq!(
|
||||
ffi::lua_gettop(state),
|
||||
expected,
|
||||
"lua stack error, expected stack to be {}, got {}",
|
||||
expected,
|
||||
top
|
||||
);
|
||||
} else {
|
||||
assert!(top >= expected,
|
||||
"lua stack error, {} too many values popped",
|
||||
top - expected);
|
||||
assert!(
|
||||
top >= expected,
|
||||
"lua stack error, {} too many values popped",
|
||||
top - expected
|
||||
);
|
||||
if top > expected {
|
||||
ffi::lua_settop(state, expected);
|
||||
}
|
||||
|
@ -60,15 +67,18 @@ pub unsafe fn stack_guard<F, R>(state: *mut ffi::lua_State, change: c_int, op: F
|
|||
// still longjmps, and have all the same dangers as longjmps, so extreme care
|
||||
// must still be taken in code that uses this function. Does not call
|
||||
// lua_checkstack, and uses 2 extra stack spaces.
|
||||
pub unsafe fn error_guard<F, R>(state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
func: F)
|
||||
-> LuaResult<R>
|
||||
where F: FnOnce(*mut ffi::lua_State) -> LuaResult<R> + UnwindSafe
|
||||
pub unsafe fn error_guard<F, R>(
|
||||
state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
func: F,
|
||||
) -> LuaResult<R>
|
||||
where
|
||||
F: FnOnce(*mut ffi::lua_State) -> LuaResult<R> + UnwindSafe,
|
||||
{
|
||||
unsafe extern "C" fn call_impl<F>(state: *mut ffi::lua_State) -> c_int
|
||||
where F: FnOnce(*mut ffi::lua_State) -> c_int
|
||||
where
|
||||
F: FnOnce(*mut ffi::lua_State) -> c_int,
|
||||
{
|
||||
let func = ffi::lua_touserdata(state, -1) as *mut F;
|
||||
let func = mem::replace(&mut *func, mem::uninitialized());
|
||||
|
@ -76,12 +86,14 @@ pub unsafe fn error_guard<F, R>(state: *mut ffi::lua_State,
|
|||
func(state)
|
||||
}
|
||||
|
||||
unsafe fn cpcall<F>(state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
mut func: F)
|
||||
-> LuaResult<()>
|
||||
where F: FnOnce(*mut ffi::lua_State) -> c_int
|
||||
unsafe fn cpcall<F>(
|
||||
state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
mut func: F,
|
||||
) -> LuaResult<()>
|
||||
where
|
||||
F: FnOnce(*mut ffi::lua_State) -> c_int,
|
||||
{
|
||||
ffi::lua_pushcfunction(state, call_impl::<F>);
|
||||
ffi::lua_insert(state, -(nargs + 1));
|
||||
|
@ -119,10 +131,10 @@ pub unsafe fn push_string(state: *mut ffi::lua_State, s: &str) {
|
|||
|
||||
pub unsafe extern "C" fn destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
||||
match catch_unwind(|| {
|
||||
let obj = &mut *(ffi::lua_touserdata(state, 1) as *mut T);
|
||||
mem::replace(obj, mem::uninitialized());
|
||||
0
|
||||
}) {
|
||||
let obj = &mut *(ffi::lua_touserdata(state, 1) as *mut T);
|
||||
mem::replace(obj, mem::uninitialized());
|
||||
0
|
||||
}) {
|
||||
Ok(r) => r,
|
||||
Err(p) => {
|
||||
push_error(state, WrappedError::Panic(p));
|
||||
|
@ -136,7 +148,8 @@ pub unsafe extern "C" fn destructor<T>(state: *mut ffi::lua_State) -> c_int {
|
|||
// longjmp). The error or panic is wrapped in such a way that when calling pop_error back on
|
||||
// the rust side, it will resume the panic.
|
||||
pub unsafe fn callback_error<R, F>(state: *mut ffi::lua_State, f: F) -> R
|
||||
where F: FnOnce() -> LuaResult<R> + UnwindSafe
|
||||
where
|
||||
F: FnOnce() -> LuaResult<R> + UnwindSafe,
|
||||
{
|
||||
match catch_unwind(f) {
|
||||
Ok(Ok(r)) => r,
|
||||
|
@ -154,8 +167,10 @@ pub unsafe fn callback_error<R, F>(state: *mut ffi::lua_State, f: F) -> R
|
|||
// Pops a WrappedError off of the top of the stack, if it is a WrappedError::Error, returns it, if
|
||||
// it is a WrappedError::Panic, clears the current stack and panics.
|
||||
pub unsafe fn pop_error(state: *mut ffi::lua_State) -> LuaError {
|
||||
assert!(ffi::lua_gettop(state) > 0,
|
||||
"pop_error called with nothing on the stack");
|
||||
assert!(
|
||||
ffi::lua_gettop(state) > 0,
|
||||
"pop_error called with nothing on the stack"
|
||||
);
|
||||
|
||||
// Pop an error off of the lua stack and interpret it as a wrapped error, or as a string. If
|
||||
// the error cannot be interpreted as a string simply print that it was an unprintable error.
|
||||
|
@ -195,10 +210,11 @@ pub unsafe fn pop_error(state: *mut ffi::lua_State) -> LuaError {
|
|||
// ffi::lua_pcall with a message handler that gives a nice traceback. If the caught error is
|
||||
// actually a LuaError, will simply pass the error along. Does not call
|
||||
// checkstack, and uses 2 extra stack spaces.
|
||||
pub unsafe fn pcall_with_traceback(state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int)
|
||||
-> c_int {
|
||||
pub unsafe fn pcall_with_traceback(
|
||||
state: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
nresults: c_int,
|
||||
) -> c_int {
|
||||
unsafe extern "C" fn message_handler(state: *mut ffi::lua_State) -> c_int {
|
||||
if is_wrapped_error(state, 1) {
|
||||
if !is_panic_error(state, 1) {
|
||||
|
@ -208,7 +224,13 @@ pub unsafe fn pcall_with_traceback(state: *mut ffi::lua_State,
|
|||
.to_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
push_error(state, WrappedError::Error(LuaError::with_chain(error, LuaErrorKind::CallbackError(traceback))));
|
||||
push_error(
|
||||
state,
|
||||
WrappedError::Error(LuaError::with_chain(
|
||||
error,
|
||||
LuaErrorKind::CallbackError(traceback),
|
||||
)),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
||||
|
@ -229,10 +251,11 @@ pub unsafe fn pcall_with_traceback(state: *mut ffi::lua_State,
|
|||
ret
|
||||
}
|
||||
|
||||
pub unsafe fn resume_with_traceback(state: *mut ffi::lua_State,
|
||||
from: *mut ffi::lua_State,
|
||||
nargs: c_int)
|
||||
-> c_int {
|
||||
pub unsafe fn resume_with_traceback(
|
||||
state: *mut ffi::lua_State,
|
||||
from: *mut ffi::lua_State,
|
||||
nargs: c_int,
|
||||
) -> c_int {
|
||||
let res = ffi::lua_resume(state, from, nargs);
|
||||
if res != ffi::LUA_OK && res != ffi::LUA_YIELD {
|
||||
if is_wrapped_error(state, 1) {
|
||||
|
@ -243,7 +266,13 @@ pub unsafe fn resume_with_traceback(state: *mut ffi::lua_State,
|
|||
.to_str()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
push_error(from, WrappedError::Error(LuaError::with_chain(error, LuaErrorKind::CallbackError(traceback))));
|
||||
push_error(
|
||||
from,
|
||||
WrappedError::Error(LuaError::with_chain(
|
||||
error,
|
||||
LuaErrorKind::CallbackError(traceback),
|
||||
)),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
||||
|
@ -314,7 +343,7 @@ unsafe fn push_error(state: *mut ffi::lua_State, err: WrappedError) {
|
|||
ffi::luaL_checkstack(state, 6, ptr::null());
|
||||
|
||||
let err_userdata = ffi::lua_newuserdata(state, mem::size_of::<Option<WrappedError>>()) as
|
||||
*mut Option<WrappedError>;
|
||||
*mut Option<WrappedError>;
|
||||
|
||||
ptr::write(err_userdata, Some(err));
|
||||
|
||||
|
@ -323,8 +352,10 @@ unsafe fn push_error(state: *mut ffi::lua_State, err: WrappedError) {
|
|||
ffi::lua_pop(state, 1);
|
||||
|
||||
ffi::lua_newtable(state);
|
||||
ffi::lua_pushlightuserdata(state,
|
||||
&ERROR_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
state,
|
||||
&ERROR_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
ffi::lua_pushvalue(state, -2);
|
||||
|
||||
push_string(state, "__gc");
|
||||
|
@ -343,9 +374,11 @@ unsafe fn push_error(state: *mut ffi::lua_State, err: WrappedError) {
|
|||
|
||||
// Checks if the error at the given index is a WrappedError::Panic
|
||||
unsafe fn is_panic_error(state: *mut ffi::lua_State, index: c_int) -> bool {
|
||||
assert_ne!(ffi::lua_checkstack(state, 2),
|
||||
0,
|
||||
"somehow not enough stack space to check if an error is panic");
|
||||
assert_ne!(
|
||||
ffi::lua_checkstack(state, 2),
|
||||
0,
|
||||
"somehow not enough stack space to check if an error is panic"
|
||||
);
|
||||
|
||||
let index = ffi::lua_absindex(state, index);
|
||||
|
||||
|
@ -380,9 +413,11 @@ unsafe fn is_panic_error(state: *mut ffi::lua_State, index: c_int) -> bool {
|
|||
}
|
||||
|
||||
unsafe fn is_wrapped_error(state: *mut ffi::lua_State, index: c_int) -> bool {
|
||||
assert_ne!(ffi::lua_checkstack(state, 2),
|
||||
0,
|
||||
"somehow not enough stack space to check if an error is rrapped");
|
||||
assert_ne!(
|
||||
ffi::lua_checkstack(state, 2),
|
||||
0,
|
||||
"somehow not enough stack space to check if an error is rrapped"
|
||||
);
|
||||
|
||||
let index = ffi::lua_absindex(state, index);
|
||||
|
||||
|
@ -402,7 +437,9 @@ unsafe fn is_wrapped_error(state: *mut ffi::lua_State, index: c_int) -> bool {
|
|||
}
|
||||
|
||||
unsafe fn get_error_metatable(state: *mut ffi::lua_State) -> c_int {
|
||||
ffi::lua_pushlightuserdata(state,
|
||||
&ERROR_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void);
|
||||
ffi::lua_pushlightuserdata(
|
||||
state,
|
||||
&ERROR_METATABLE_REGISTRY_KEY as *const u8 as *mut c_void,
|
||||
);
|
||||
ffi::lua_gettable(state, ffi::LUA_REGISTRYINDEX)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue