Add support for full userdata with proper dropping support
This commit is contained in:
parent
3777db69de
commit
10efbfdd16
|
@ -1 +1 @@
|
|||
/target
|
||||
target/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(c_unwind)]
|
||||
#![feature(thread_id_value)]
|
||||
#![feature(const_btree_new)]
|
||||
|
||||
pub use libloading;
|
||||
pub use detour;
|
||||
|
|
|
@ -168,6 +168,7 @@ pub struct LuaShared {
|
|||
pub lua_getstack: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, level: i32, ar: *mut LuaDebug) -> i32>,
|
||||
pub lua_next: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, index: i32) -> i32>,
|
||||
pub lua_topointer: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, index: i32) -> *const c_void>,
|
||||
pub lua_newuserdata: Symbol<'static, unsafe extern "C-unwind" fn(state: LuaState, size: usize) -> *mut c_void>,
|
||||
}
|
||||
unsafe impl Sync for LuaShared {}
|
||||
impl LuaShared {
|
||||
|
@ -232,7 +233,8 @@ impl LuaShared {
|
|||
lua_getinfo: find_symbol!("lua_getinfo"),
|
||||
lua_getstack: find_symbol!("lua_getstack"),
|
||||
lua_next: find_symbol!("lua_next"),
|
||||
lua_topointer: find_symbol!("lua_topointer")
|
||||
lua_topointer: find_symbol!("lua_topointer"),
|
||||
lua_newuserdata: find_symbol!("lua_newuserdata"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -386,6 +386,40 @@ impl LuaState {
|
|||
(LUA_SHARED.lua_topointer)(*self, index)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn to_userdata(&self, index: i32) -> *mut c_void {
|
||||
(LUA_SHARED.lua_touserdata)(*self, index)
|
||||
}
|
||||
|
||||
pub unsafe fn new_userdata<T: Sized>(&self, data: T, metatable: Option<i32>) -> *mut T {
|
||||
let has_metatable = if std::mem::needs_drop::<T>() {
|
||||
if let Some(metatable) = metatable {
|
||||
self.push_value(metatable);
|
||||
} else {
|
||||
self.new_table();
|
||||
}
|
||||
self.push_function(crate::userdata::__gc::<T>);
|
||||
self.set_field(-2, crate::lua_string!("__gc"));
|
||||
true
|
||||
} else if let Some(metatable) = metatable {
|
||||
self.push_value(metatable);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let ptr = (LUA_SHARED.lua_newuserdata)(*self, std::mem::size_of::<T>()) as *mut T;
|
||||
|
||||
if has_metatable {
|
||||
self.push_value(-2);
|
||||
self.set_metatable(-2);
|
||||
self.remove(-2);
|
||||
}
|
||||
|
||||
ptr.write(data);
|
||||
ptr
|
||||
}
|
||||
|
||||
pub unsafe fn error<S: AsRef<str>>(&self, msg: S) -> ! {
|
||||
self.push_string(msg.as_ref());
|
||||
(LUA_SHARED.lua_error)(*self);
|
||||
|
|
|
@ -110,3 +110,9 @@ userdata! {
|
|||
UserData::Vector => Vector,
|
||||
UserData::Angle => Angle
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C-unwind" fn __gc<T: Sized>(lua: crate::lua::State) -> i32 {
|
||||
let userdata = lua.to_userdata(1) as *mut T;
|
||||
std::ptr::read(userdata);
|
||||
0
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
*/target/
|
|
@ -0,0 +1,386 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_table"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f3690291e34881a89ceb8e80802f1582f29b1361fd476eeefb4e89dd6a121e"
|
||||
|
||||
[[package]]
|
||||
name = "cstr"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2846d3636dcaff720d311ea8983f5fa7a8288632b2f95145dd4b5819c397fd8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "detour"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3c83fabcc3bc336e19320c13576ea708a15deec201d6b879b7ad1b92734d7b9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"generic-array",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libudis86-sys",
|
||||
"mmap-fixed",
|
||||
"region",
|
||||
"slice-pool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fn_abi"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "451b828bd3c5f19949222834f58b38c3670604dcaa5f2b7aec50c0cd58f34900"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn_squash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fn_has_this"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb93938067213676967092012a53515e926de7c813afccd9b075ba0ec78dbba9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn_squash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fn_type_alias"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e807f01217f1f89959fbeebd10c6471b5ef3971fce1b02a70fb7212cc6c1f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gmod"
|
||||
version = "6.0.1"
|
||||
dependencies = [
|
||||
"cfg_table",
|
||||
"cstr",
|
||||
"ctor",
|
||||
"detour",
|
||||
"fn_abi",
|
||||
"fn_has_this",
|
||||
"fn_type_alias",
|
||||
"gmod-macros",
|
||||
"lazy_static",
|
||||
"libloading",
|
||||
"null_fn",
|
||||
"skidscan",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gmod-macros"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libudis86-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "139bbf9ddb1bfc90c1ac64dd2923d9c957cd433cee7315c018125d72ab08a6b0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mmap-fixed"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27c1ae264d6343d3b4079549f6bc9e6d074dc4106cb1324c7753c6ce11d07b21"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "null_fn"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "345919cfb52d0d8da7efc21aea56046ca96d9e3a8adfdbdb27ef1172829976c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "region"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"mach",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
|
||||
[[package]]
|
||||
name = "skidscan"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e599f7639f0115549da310b45dc29319858981e20dd5e15ee66f69fc8219092e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"skidscan-macros",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "skidscan-macros"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "881ef2150f0e4e2a855bb661a3ecd621ab1b6aa07b34aef941d1bd37b4267e8d"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slice-pool"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "733fc6e5f1bd3a8136f842c9bdea4e5f17c910c2fcc98c90c3aa7604ef5e2e7a"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn_squash"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134b985708d02b2569ab2b9e27c8758ca4baaaf725341a572d59bc2d174b9bb5"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "userdata"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gmod",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "userdata"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
gmod = { path = "../../gmod" }
|
||||
|
||||
[workspace]
|
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
|
@ -0,0 +1,76 @@
|
|||
#![feature(c_unwind)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate gmod;
|
||||
|
||||
static mut DROP_OK: bool = false;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct DropMe {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub z: i32,
|
||||
pub hello: String
|
||||
}
|
||||
impl Drop for DropMe {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if DROP_OK {
|
||||
DROP_OK = false;
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
println!("USERDATA DROP TEST PASSED");
|
||||
} else {
|
||||
panic!("Dropped too early or too late");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! drop_me {
|
||||
() => {
|
||||
DropMe {
|
||||
x: 69,
|
||||
y: 420,
|
||||
z: 123,
|
||||
hello: "Hello".to_string()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[gmod13_open]
|
||||
unsafe fn gmod13_open(lua: gmod::lua::State) -> i32 {
|
||||
let ud = lua.new_userdata(drop_me!(), None);
|
||||
assert_eq!(&*ud, Box::leak(Box::new(drop_me!())));
|
||||
|
||||
lua.set_global(lua_string!("GMOD_RUST_DROP_TEST"));
|
||||
|
||||
lua.push_nil();
|
||||
lua.set_global(lua_string!("GMOD_RUST_DROP_TEST"));
|
||||
DROP_OK = true;
|
||||
|
||||
lua.get_global(lua_string!("collectgarbage"));
|
||||
lua.push_value(-1);
|
||||
lua.call(0, 0);
|
||||
lua.call(0, 0);
|
||||
|
||||
let ud = lua.new_userdata(420_i32, None);
|
||||
assert_eq!(*ud, 420_i32);
|
||||
|
||||
lua.get_global(lua_string!("collectgarbage"));
|
||||
lua.push_value(-1);
|
||||
lua.call(0, 0);
|
||||
lua.call(0, 0);
|
||||
|
||||
0
|
||||
}
|
Loading…
Reference in New Issue