From ebe54926fb08c0ca2f57f9ba291843e7df998139 Mon Sep 17 00:00:00 2001 From: notnotmelon Date: Wed, 21 Aug 2024 10:33:02 -0500 Subject: [PATCH 1/4] feat: implement several direct hooks into luaC API --- src/lua/luac_interface.rs | 143 +++++++++++++++++++++++++++++++++++++- src/lua/luastate.rs | 15 ++-- 2 files changed, 150 insertions(+), 8 deletions(-) diff --git a/src/lua/luac_interface.rs b/src/lua/luac_interface.rs index de6254a..ec510a7 100644 --- a/src/lua/luac_interface.rs +++ b/src/lua/luac_interface.rs @@ -1,6 +1,145 @@ use crate as rivets; -use crate::lua::luastate; +use crate::lua::{lua_Debug, lua_State}; use rivets_macros::import; +use std::ffi::{c_char, c_int, c_uint, c_void}; + +use super::{lua_CFunction, lua_Hook, lua_Writer}; + +#[import(lua_absindex)] +pub extern "C" fn lua_absindex(lua_state: *mut lua_State, index: c_uint) -> c_int {} + +#[import(lua_arith)] +pub extern "C" fn lua_arith(lua_state: *mut lua_State, op: c_int) {} + +#[import(lua_atpanic)] +pub extern "C" fn lua_atpanic(lua_state: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction {} + +#[import(lua_callk)] +pub extern "C" fn lua_callk( + lua_state: *mut lua_State, + nargs: c_int, + nresults: c_int, + ctx: c_int, + k: lua_CFunction, +) { +} + +#[import(lua_checkstack)] +pub extern "C" fn lua_checkstack(lua_state: *mut lua_State, size: c_int) -> c_int {} + +#[import(lua_close)] +pub extern "C" fn lua_close(lua_state: *mut lua_State) {} + +#[import(lua_compare)] +pub extern "C" fn lua_compare( + lua_state: *mut lua_State, + index_1: c_int, + index_2: c_int, + operator: c_int, +) -> c_int { +} + +#[import(lua_concat)] +pub extern "C" fn lua_concat(lua_state: *mut lua_State, n: c_int) {} + +#[import(lua_copy)] +pub extern "C" fn lua_copy(lua_state: *mut lua_State, from_index: c_int, to_index: c_int) {} + +#[import(lua_createtable)] +pub extern "C" fn lua_createtable(lua_state: *mut lua_State, narray: c_int, nrec: c_int) {} + +#[import(lua_dump)] +pub extern "C" fn lua_dump( + lua_state: *mut lua_State, + writer: lua_Writer, + data: *mut c_void, +) -> c_int { +} + +#[import(lua_error)] +pub extern "C" fn lua_error(lua_state: *mut lua_State) {} + +#[import(lua_gc)] +pub extern "C" fn lua_gc(lua_state: *mut lua_State, what: c_int, data: c_int) -> c_int {} + +//#[import(lua_getallocf)] +//pub extern "C" fn lua_getallocf(lua_state: *mut lua_State, ud: *mut *mut c_void) -> luastate::lua_Alloc {} + +#[import(lua_getctx)] +pub extern "C" fn lua_getctx(lua_state: *mut lua_State, ctx: *mut c_int) -> c_int {} + +#[import(lua_getfield)] +pub extern "C" fn lua_getfield(lua_state: *mut lua_State, index: c_int, k: *const c_char) -> c_int { +} + +#[import(lua_getglobal)] +pub extern "C" fn lua_getglobal( + lua_state: *mut lua_State, + global_varible_name: *const c_char, +) -> c_int { +} + +#[import(lua_gethook)] +pub extern "C" fn lua_gethook(lua_state: *mut lua_State) -> lua_Hook {} + +#[import(lua_gethookcount)] +pub extern "C" fn lua_gethookcount(lua_state: *mut lua_State) -> c_int {} + +#[import(lua_gethookmask)] +pub extern "C" fn lua_gethookmask(lua_state: *mut lua_State) -> c_int {} + +#[import(lua_getinfo)] +pub extern "C" fn lua_getinfo( + lua_state: *mut lua_State, + what: *const c_char, + ar: *mut lua_Debug, +) -> c_int { +} + +#[import(lua_getlocal)] +pub extern "C" fn lua_getlocal( + lua_state: *mut lua_State, + ar: *const lua_Debug, + n: c_int, +) -> *const c_char { +} + +#[import(lua_getmetatable)] +pub extern "C" fn lua_getmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int {} + +#[import(lua_getstack)] +pub extern "C" fn lua_getstack( + lua_state: *mut lua_State, + level: c_int, + ar: *mut lua_Debug, +) -> c_int { +} + +#[import(lua_gettable)] +pub extern "C" fn lua_gettable(lua_state: *mut lua_State, index: c_int) {} #[import(lua_gettop)] -pub extern "C" fn get_top(lua_state: *mut luastate::lua_State) -> i64 {} +pub extern "C" fn lua_gettop(lua_state: *mut lua_State) -> c_int {} + +#[import(lua_getupvalue)] +pub extern "C" fn lua_getupvalue( + lua_state: *mut lua_State, + function_index: c_int, + upvalue_index: c_int, +) -> *const c_char { +} + +#[import(lua_getuservalue)] +pub extern "C" fn lua_getuservalue(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_insert)] +pub extern "C" fn lua_insert(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_iscfunction)] +pub extern "C" fn lua_iscfunction(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_isnumberorstringconvertabletonumber)] +pub extern "C" fn lua_isnumber(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_isstringornumberconvertabletostring)] +pub extern "C" fn lua_isstring(lua_state: *mut lua_State, index: c_int) -> c_int {} diff --git a/src/lua/luastate.rs b/src/lua/luastate.rs index 6c12e3c..72cc213 100644 --- a/src/lua/luastate.rs +++ b/src/lua/luastate.rs @@ -5,17 +5,20 @@ use std::ffi::{ }; use std::fmt::Debug; -type size_t = c_ulong; // c_size_t is nightly only, defaults to usize currently -> 64 bit -type lu_byte = c_char; -type lua_Number = c_double; -type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int; -type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug); -type lua_Alloc = unsafe extern "C-unwind" fn( +pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int; +pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug); +pub type lua_Alloc = unsafe extern "C-unwind" fn( ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize, ) -> *mut c_void; +pub type lua_Writer = + unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int; + +type size_t = c_ulong; // c_size_t is nightly only, defaults to usize currently -> 64 bit +type lu_byte = c_char; +type lua_Number = c_double; type Instruction = c_uint; // 32 bit type ptrdiff_t = isize; // https://en.cppreference.com/w/cpp/types/ptrdiff_t type luai_jmpbuf = c_int; From b4195dee85f59943ecd8a87bdca3df53f6f87248 Mon Sep 17 00:00:00 2001 From: notnotmelon Date: Wed, 21 Aug 2024 21:08:41 -0500 Subject: [PATCH 2/4] refactor: Rewrite the macros crate. Prevent compiler warning in standard use. --- rivets-macros/Cargo.toml | 1 + rivets-macros/src/{lib.rs => macros.rs} | 75 +++++++++++-------------- rivets-shared/src/lib.rs | 6 +- src/lua/luac_interface.rs | 64 ++++++++++----------- src/lua/luastate.rs | 2 +- 5 files changed, 71 insertions(+), 77 deletions(-) rename rivets-macros/src/{lib.rs => macros.rs} (90%) diff --git a/rivets-macros/Cargo.toml b/rivets-macros/Cargo.toml index 6cdd8e6..28e6034 100644 --- a/rivets-macros/Cargo.toml +++ b/rivets-macros/Cargo.toml @@ -17,3 +17,4 @@ darling = "0.20" [lib] proc-macro = true +path = "src/macros.rs" \ No newline at end of file diff --git a/rivets-macros/src/lib.rs b/rivets-macros/src/macros.rs similarity index 90% rename from rivets-macros/src/lib.rs rename to rivets-macros/src/macros.rs index 71614d4..39f33fa 100644 --- a/rivets-macros/src/lib.rs +++ b/rivets-macros/src/macros.rs @@ -1,42 +1,39 @@ -#![warn(missing_docs)] #![feature(proc_macro_diagnostic)] +#![warn(missing_docs)] //! Contains the proc macros for rivets. use anyhow::{bail, Result}; use darling::FromDeriveInput; use lazy_regex::regex; -use proc_macro::{self, Diagnostic, Level, Span, TokenStream}; +use proc_macro::{Diagnostic, Level, Span, TokenStream}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use std::sync::{atomic::AtomicBool, LazyLock, Mutex}; -use syn::{parse_macro_input, Abi, DeriveInput, Error, Expr, FnArg, Ident, ItemFn, Variant}; +use syn::{parse_macro_input, Abi, DeriveInput, Expr, FnArg, Ident, ItemFn, Variant}; static IS_FINALIZED: AtomicBool = AtomicBool::new(false); static MANGLED_NAMES: LazyLock>> = LazyLock::new(|| Mutex::new(vec![])); static CPP_IMPORTS: LazyLock>> = LazyLock::new(|| Mutex::new(vec![])); -macro_rules! derive_error { - ($string: tt) => { - Error::new(proc_macro2::Span::call_site(), $string) - .to_compile_error() - .into() - }; -} - -macro_rules! check_finalized { - () => { - // this check causes issues with rust-analyer. disable during debug builds. - #[cfg(not(debug_assertions))] - if IS_FINALIZED.load(std::sync::atomic::Ordering::Relaxed) { - panic!("The rivets library has already been finalized!"); - } - }; +fn derive_error(error_message: &str) -> TokenStream { + Diagnostic::spanned(Span::call_site(), Level::Error, error_message).emit(); + quote!{}.into() } -fn failure(callback: proc_macro2::TokenStream, error_message: &str) -> TokenStream { - Diagnostic::spanned(Span::call_site(), Level::Error, error_message).emit(); - callback.into() +/// Asserts if the rivets library has already been finalized. +/// This check is preformed in the following proc macros: +/// - `detour` +/// - `import` +/// - `finalize` +/// +/// Note that this check is only preformed in release builds. +fn check_finalized() { + // this check causes issues with rust-analyer. disable during debug builds. + #[cfg(not(debug_assertions))] + if IS_FINALIZED.load(std::sync::atomic::Ordering::Relaxed) { + panic!("The rivets library has already been finalized!"); + } } fn determine_calling_convention(input: &ItemFn, unmangled_name: &str) -> Result { @@ -47,7 +44,7 @@ fn determine_calling_convention(input: &ItemFn, unmangled_name: &str) -> Result< let abi = regex!(r" __[a-zA-Z]+ ").find(unmangled_name); let abi = match abi { Some(abi) => abi.as_str(), - None => bail!("Failed to automatically determine calling convention for {unmangled_name}. Try specifying the calling convention manually. Example: extern \"C\" fn() {}", "{}"), + None => bail!("Failed to automatically determine calling convention for {unmangled_name}. Try specifying the calling convention manually. Example: extern \"C-unwind\" fn() {}", "{}"), }; let abi = &abi[1..abi.len() - 1]; if let Some(calling_convention) = rivets_shared::get_calling_convention(abi) { @@ -103,7 +100,7 @@ fn determine_calling_convention(input: &ItemFn, unmangled_name: &str) -> Result< /// See the `pdb2hpp` module for a tool that can generate the correct FFI types for C++ functions. #[proc_macro_attribute] pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { - check_finalized!(); + check_finalized(); let mangled_name = attr.to_string(); let unmangled_name = @@ -134,8 +131,8 @@ pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { let arg_names = quote! { #( #arg_names ),* }; let calling_convention = match determine_calling_convention(&input, &unmangled_name) { - Ok(calling_convention) => calling_convention, - Err(e) => return failure(quote! { #input }, &e.to_string()), + Ok(calling_convention) => Some(calling_convention), + Err(e) => return derive_error(&e.to_string()), }; input.sig.abi = None; let callback = quote! { #input }; @@ -152,12 +149,11 @@ pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { static Detour : #cpp_function_header; } + #[doc = #unmangled_name] unsafe fn back(#inputs) #return_type { Detour.call(#arg_names) } - #[doc = #unmangled_name] - #[allow(unused_variables)] #callback pub unsafe fn hook(address: u64) -> Result<(), rivets::retour::Error> { @@ -173,8 +169,6 @@ pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { .expect("Failed to lock mangled names") .push((mangled_name.clone(), name.to_string())); - Diagnostic::spanned(Span::call_site(), Level::Note, unmangled_name.clone()).emit(); - result.into() } @@ -216,7 +210,7 @@ pub fn detour(attr: TokenStream, item: TokenStream) -> TokenStream { /// Calling any imported function repersents calling into the C++ compiled codebase and thus is inherently unsafe. #[proc_macro_attribute] pub fn import(attr: TokenStream, item: TokenStream) -> TokenStream { - check_finalized!(); + check_finalized(); let mangled_name = attr.to_string(); let unmangled_name = @@ -226,7 +220,7 @@ pub fn import(attr: TokenStream, item: TokenStream) -> TokenStream { let calling_convention = match determine_calling_convention(&input, &unmangled_name) { Ok(calling_convention) => Some(calling_convention), - Err(e) => return failure(quote! { #input }, &e.to_string()), + Err(e) => return derive_error(&e.to_string()), }; let arg_types = input.sig.inputs.iter().map(|arg| match arg { @@ -252,12 +246,11 @@ pub fn import(attr: TokenStream, item: TokenStream) -> TokenStream { .expect("Failed to lock cpp imports") .push((mangled_name.clone(), name.to_string())); - Diagnostic::spanned(Span::call_site(), Level::Note, unmangled_name.clone()).emit(); - quote! { + #[doc = #unmangled_name] #[allow(non_upper_case_globals)] #[allow(missing_docs)] - #attr #vis static mut #name: rivets::UnsafeSummonedFunction<#function_type> = rivets::UnsafeSummonedFunction::Uninitialized; + #attr #vis static mut #name: rivets::UnsafeImportedFunction<#function_type> = rivets::UnsafeImportedFunction::Uninitialized; }.into() } @@ -295,7 +288,7 @@ fn get_imports() -> Vec { let function = unsafe { std::mem::transmute(address) // todo: rust documentation recommends casting this to a raw function pointer. address as *const _ }; - unsafe { #rust_name = rivets::UnsafeSummonedFunction::Function(function); } + unsafe { #rust_name = rivets::UnsafeImportedFunction::Function(function); } } }) .collect() @@ -306,7 +299,7 @@ fn get_imports() -> Vec { /// It will finalize the rivets library and inject all of the detours. #[proc_macro] pub fn finalize(_: TokenStream) -> TokenStream { - check_finalized!(); + check_finalized(); IS_FINALIZED.store(true, std::sync::atomic::Ordering::Relaxed); let hooks = get_hooks(); @@ -347,12 +340,12 @@ struct DefineOpts { pub fn define_derive(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input); let Ok(DefineOpts { kind }) = DefineOpts::from_derive_input(&input) else { - return derive_error!("Missing #[kind(?)] attribute!"); + return derive_error("Missing #[kind(?)] attribute!"); }; let DeriveInput { ident, data, .. } = input; let syn::Data::Enum(data) = data else { - return derive_error!("FactorioDefine can only be used on enums!"); + return derive_error("FactorioDefine can only be used on enums!"); }; let count = data.variants.len(); @@ -372,7 +365,7 @@ pub fn define_derive(input: TokenStream) -> TokenStream { } let Expr::Lit(syn::PatLit { lit, .. }) = &nv.value else { - return derive_error!("All variants must have a #[value(?)] attribute!"); + return derive_error("All variants must have a #[value(?)] attribute!"); }; value = Some(lit.clone()); @@ -381,7 +374,7 @@ pub fn define_derive(input: TokenStream) -> TokenStream { } let Some(value) = value else { - return derive_error!("All variants must have a #[value = ?] attribute!"); + return derive_error("All variants must have a #[value = ?] attribute!"); }; let Variant { ident, .. } = variant; diff --git a/rivets-shared/src/lib.rs b/rivets-shared/src/lib.rs index 2a7c069..d818acb 100644 --- a/rivets-shared/src/lib.rs +++ b/rivets-shared/src/lib.rs @@ -159,7 +159,7 @@ impl SymbolCache { /// Represents a function that has been imported from a C++ compiled DLL. /// Invariant: If the function is not initialized, it is UB to dereference it. /// The rivets::finalize!() macro should be used to ensure that the function is initialized. -pub enum UnsafeSummonedFunction +pub enum UnsafeImportedFunction where T: 'static + Sized, { @@ -167,7 +167,7 @@ where Uninitialized, } -impl Deref for UnsafeSummonedFunction { +impl Deref for UnsafeImportedFunction { type Target = T; #[inline] @@ -175,7 +175,7 @@ impl Deref for UnsafeSummonedFunction { fn deref(&self) -> &Self::Target { match self { Self::Function(x) => x, - Self::Uninitialized => unsafe { std::hint::unreachable_unchecked() }, + Self::Uninitialized => unreachable!("Attempted to dereference an uninitialized imported function pointer! This is a bug in rivets core, please report it."), } } } diff --git a/src/lua/luac_interface.rs b/src/lua/luac_interface.rs index ec510a7..65ec5ec 100644 --- a/src/lua/luac_interface.rs +++ b/src/lua/luac_interface.rs @@ -6,16 +6,16 @@ use std::ffi::{c_char, c_int, c_uint, c_void}; use super::{lua_CFunction, lua_Hook, lua_Writer}; #[import(lua_absindex)] -pub extern "C" fn lua_absindex(lua_state: *mut lua_State, index: c_uint) -> c_int {} +pub extern "C-unwind" fn lua_absindex(lua_state: *mut lua_State, index: c_uint) -> c_int {} #[import(lua_arith)] -pub extern "C" fn lua_arith(lua_state: *mut lua_State, op: c_int) {} +pub extern "C-unwind" fn lua_arith(lua_state: *mut lua_State, op: c_int) {} #[import(lua_atpanic)] -pub extern "C" fn lua_atpanic(lua_state: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction {} +pub extern "C-unwind" fn lua_atpanic(lua_state: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction {} #[import(lua_callk)] -pub extern "C" fn lua_callk( +pub extern "C-unwind" fn lua_callk( lua_state: *mut lua_State, nargs: c_int, nresults: c_int, @@ -25,13 +25,13 @@ pub extern "C" fn lua_callk( } #[import(lua_checkstack)] -pub extern "C" fn lua_checkstack(lua_state: *mut lua_State, size: c_int) -> c_int {} +pub extern "C-unwind" fn lua_checkstack(lua_state: *mut lua_State, size: c_int) -> c_int {} #[import(lua_close)] -pub extern "C" fn lua_close(lua_state: *mut lua_State) {} +pub extern "C-unwind" fn lua_close(lua_state: *mut lua_State) {} #[import(lua_compare)] -pub extern "C" fn lua_compare( +pub extern "C-unwind" fn lua_compare( lua_state: *mut lua_State, index_1: c_int, index_2: c_int, @@ -40,16 +40,16 @@ pub extern "C" fn lua_compare( } #[import(lua_concat)] -pub extern "C" fn lua_concat(lua_state: *mut lua_State, n: c_int) {} +pub extern "C-unwind" fn lua_concat(lua_state: *mut lua_State, n: c_int) {} #[import(lua_copy)] -pub extern "C" fn lua_copy(lua_state: *mut lua_State, from_index: c_int, to_index: c_int) {} +pub extern "C-unwind" fn lua_copy(lua_state: *mut lua_State, from_index: c_int, to_index: c_int) {} #[import(lua_createtable)] -pub extern "C" fn lua_createtable(lua_state: *mut lua_State, narray: c_int, nrec: c_int) {} +pub extern "C-unwind" fn lua_createtable(lua_state: *mut lua_State, narray: c_int, nrec: c_int) {} #[import(lua_dump)] -pub extern "C" fn lua_dump( +pub extern "C-unwind" fn lua_dump( lua_state: *mut lua_State, writer: lua_Writer, data: *mut c_void, @@ -57,39 +57,39 @@ pub extern "C" fn lua_dump( } #[import(lua_error)] -pub extern "C" fn lua_error(lua_state: *mut lua_State) {} +pub extern "C-unwind" fn lua_error(lua_state: *mut lua_State) {} #[import(lua_gc)] -pub extern "C" fn lua_gc(lua_state: *mut lua_State, what: c_int, data: c_int) -> c_int {} +pub extern "C-unwind" fn lua_gc(lua_state: *mut lua_State, what: c_int, data: c_int) -> c_int {} //#[import(lua_getallocf)] -//pub extern "C" fn lua_getallocf(lua_state: *mut lua_State, ud: *mut *mut c_void) -> luastate::lua_Alloc {} +//pub extern "C-unwind" fn lua_getallocf(lua_state: *mut lua_State, ud: *mut *mut c_void) -> luastate::lua_Alloc {} #[import(lua_getctx)] -pub extern "C" fn lua_getctx(lua_state: *mut lua_State, ctx: *mut c_int) -> c_int {} +pub extern "C-unwind" fn lua_getctx(lua_state: *mut lua_State, ctx: *mut c_int) -> c_int {} #[import(lua_getfield)] -pub extern "C" fn lua_getfield(lua_state: *mut lua_State, index: c_int, k: *const c_char) -> c_int { +pub extern "C-unwind" fn lua_getfield(lua_state: *mut lua_State, index: c_int, k: *const c_char) -> c_int { } #[import(lua_getglobal)] -pub extern "C" fn lua_getglobal( +pub extern "C-unwind" fn lua_getglobal( lua_state: *mut lua_State, global_varible_name: *const c_char, ) -> c_int { } #[import(lua_gethook)] -pub extern "C" fn lua_gethook(lua_state: *mut lua_State) -> lua_Hook {} +pub extern "C-unwind" fn lua_gethook(lua_state: *mut lua_State) -> lua_Hook {} #[import(lua_gethookcount)] -pub extern "C" fn lua_gethookcount(lua_state: *mut lua_State) -> c_int {} +pub extern "C-unwind" fn lua_gethookcount(lua_state: *mut lua_State) -> c_int {} #[import(lua_gethookmask)] -pub extern "C" fn lua_gethookmask(lua_state: *mut lua_State) -> c_int {} +pub extern "C-unwind" fn lua_gethookmask(lua_state: *mut lua_State) -> c_int {} #[import(lua_getinfo)] -pub extern "C" fn lua_getinfo( +pub extern "C-unwind" fn lua_getinfo( lua_state: *mut lua_State, what: *const c_char, ar: *mut lua_Debug, @@ -97,7 +97,7 @@ pub extern "C" fn lua_getinfo( } #[import(lua_getlocal)] -pub extern "C" fn lua_getlocal( +pub extern "C-unwind" fn lua_getlocal( lua_state: *mut lua_State, ar: *const lua_Debug, n: c_int, @@ -105,10 +105,10 @@ pub extern "C" fn lua_getlocal( } #[import(lua_getmetatable)] -pub extern "C" fn lua_getmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int {} +pub extern "C-unwind" fn lua_getmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int {} #[import(lua_getstack)] -pub extern "C" fn lua_getstack( +pub extern "C-unwind" fn lua_getstack( lua_state: *mut lua_State, level: c_int, ar: *mut lua_Debug, @@ -116,13 +116,13 @@ pub extern "C" fn lua_getstack( } #[import(lua_gettable)] -pub extern "C" fn lua_gettable(lua_state: *mut lua_State, index: c_int) {} +pub extern "C-unwind" fn lua_gettable(lua_state: *mut lua_State, index: c_int) {} #[import(lua_gettop)] -pub extern "C" fn lua_gettop(lua_state: *mut lua_State) -> c_int {} +pub extern "C-unwind" fn lua_gettop(lua_state: *mut lua_State) -> c_int {} #[import(lua_getupvalue)] -pub extern "C" fn lua_getupvalue( +pub extern "C-unwind" fn lua_getupvalue( lua_state: *mut lua_State, function_index: c_int, upvalue_index: c_int, @@ -130,16 +130,16 @@ pub extern "C" fn lua_getupvalue( } #[import(lua_getuservalue)] -pub extern "C" fn lua_getuservalue(lua_state: *mut lua_State, index: c_int) {} +pub extern "C-unwind" fn lua_getuservalue(lua_state: *mut lua_State, index: c_int) {} #[import(lua_insert)] -pub extern "C" fn lua_insert(lua_state: *mut lua_State, index: c_int) {} +pub extern "C-unwind" fn lua_insert(lua_state: *mut lua_State, index: c_int) {} #[import(lua_iscfunction)] -pub extern "C" fn lua_iscfunction(lua_state: *mut lua_State, index: c_int) -> c_int {} +pub extern "C-unwind" fn lua_iscfunction(lua_state: *mut lua_State, index: c_int) -> c_int {} #[import(lua_isnumberorstringconvertabletonumber)] -pub extern "C" fn lua_isnumber(lua_state: *mut lua_State, index: c_int) -> c_int {} +pub extern "C-unwind" fn lua_isnumber(lua_state: *mut lua_State, index: c_int) -> c_int {} #[import(lua_isstringornumberconvertabletostring)] -pub extern "C" fn lua_isstring(lua_state: *mut lua_State, index: c_int) -> c_int {} +pub extern "C-unwind" fn lua_isstring(lua_state: *mut lua_State, index: c_int) -> c_int {} diff --git a/src/lua/luastate.rs b/src/lua/luastate.rs index 72cc213..87eee51 100644 --- a/src/lua/luastate.rs +++ b/src/lua/luastate.rs @@ -14,7 +14,7 @@ pub type lua_Alloc = unsafe extern "C-unwind" fn( nsize: usize, ) -> *mut c_void; pub type lua_Writer = - unsafe extern "C" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int; + unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int; type size_t = c_ulong; // c_size_t is nightly only, defaults to usize currently -> 64 bit type lu_byte = c_char; From d0ad8f9ebe248b86087b1b32746a8cb863f03b90 Mon Sep 17 00:00:00 2001 From: notnotmelon Date: Thu, 22 Aug 2024 13:01:49 -0500 Subject: [PATCH 3/4] feat: #[import] all luac api hooks --- rivets-macros/src/macros.rs | 4 +- src/lib.rs | 1 + src/lua/luac_interface.rs | 326 +++++++++++++++++++++++++++++++++++- src/lua/luastate.rs | 42 +++-- 4 files changed, 350 insertions(+), 23 deletions(-) diff --git a/rivets-macros/src/macros.rs b/rivets-macros/src/macros.rs index 39f33fa..ec9a7c6 100644 --- a/rivets-macros/src/macros.rs +++ b/rivets-macros/src/macros.rs @@ -18,7 +18,7 @@ static CPP_IMPORTS: LazyLock>> = LazyLock::new(|| Mu fn derive_error(error_message: &str) -> TokenStream { Diagnostic::spanned(Span::call_site(), Level::Error, error_message).emit(); - quote!{}.into() + quote! {}.into() } /// Asserts if the rivets library has already been finalized. @@ -26,7 +26,7 @@ fn derive_error(error_message: &str) -> TokenStream { /// - `detour` /// - `import` /// - `finalize` -/// +/// /// Note that this check is only preformed in release builds. fn check_finalized() { // this check causes issues with rust-analyer. disable during debug builds. diff --git a/src/lib.rs b/src/lib.rs index 4bd23a8..82bac4a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] #![warn(missing_docs)] +#![feature(c_size_t)] pub mod defines; pub mod lua; diff --git a/src/lua/luac_interface.rs b/src/lua/luac_interface.rs index 65ec5ec..1d2b3af 100644 --- a/src/lua/luac_interface.rs +++ b/src/lua/luac_interface.rs @@ -1,9 +1,13 @@ use crate as rivets; use crate::lua::{lua_Debug, lua_State}; +use core::ffi::c_size_t; use rivets_macros::import; use std::ffi::{c_char, c_int, c_uint, c_void}; -use super::{lua_CFunction, lua_Hook, lua_Writer}; +use super::{ + lua_Alloc, lua_CFunction, lua_Hook, lua_Integer, lua_Number, lua_Reader, lua_Unsigned, + lua_Writer, +}; #[import(lua_absindex)] pub extern "C-unwind" fn lua_absindex(lua_state: *mut lua_State, index: c_uint) -> c_int {} @@ -12,7 +16,11 @@ pub extern "C-unwind" fn lua_absindex(lua_state: *mut lua_State, index: c_uint) pub extern "C-unwind" fn lua_arith(lua_state: *mut lua_State, op: c_int) {} #[import(lua_atpanic)] -pub extern "C-unwind" fn lua_atpanic(lua_state: *mut lua_State, panicf: lua_CFunction) -> lua_CFunction {} +pub extern "C-unwind" fn lua_atpanic( + lua_state: *mut lua_State, + panicf: lua_CFunction, +) -> lua_CFunction { +} #[import(lua_callk)] pub extern "C-unwind" fn lua_callk( @@ -20,7 +28,7 @@ pub extern "C-unwind" fn lua_callk( nargs: c_int, nresults: c_int, ctx: c_int, - k: lua_CFunction, + k: Option, ) { } @@ -62,14 +70,22 @@ pub extern "C-unwind" fn lua_error(lua_state: *mut lua_State) {} #[import(lua_gc)] pub extern "C-unwind" fn lua_gc(lua_state: *mut lua_State, what: c_int, data: c_int) -> c_int {} -//#[import(lua_getallocf)] -//pub extern "C-unwind" fn lua_getallocf(lua_state: *mut lua_State, ud: *mut *mut c_void) -> luastate::lua_Alloc {} +#[import(lua_getallocf)] +pub extern "C-unwind" fn lua_getallocf( + lua_state: *mut lua_State, + ud: *mut *mut c_void, +) -> lua_Alloc { +} #[import(lua_getctx)] pub extern "C-unwind" fn lua_getctx(lua_state: *mut lua_State, ctx: *mut c_int) -> c_int {} #[import(lua_getfield)] -pub extern "C-unwind" fn lua_getfield(lua_state: *mut lua_State, index: c_int, k: *const c_char) -> c_int { +pub extern "C-unwind" fn lua_getfield( + lua_state: *mut lua_State, + index: c_int, + k: *const c_char, +) -> c_int { } #[import(lua_getglobal)] @@ -80,7 +96,7 @@ pub extern "C-unwind" fn lua_getglobal( } #[import(lua_gethook)] -pub extern "C-unwind" fn lua_gethook(lua_state: *mut lua_State) -> lua_Hook {} +pub extern "C-unwind" fn lua_gethook(lua_state: *mut lua_State) -> Option {} #[import(lua_gethookcount)] pub extern "C-unwind" fn lua_gethookcount(lua_state: *mut lua_State) -> c_int {} @@ -105,7 +121,8 @@ pub extern "C-unwind" fn lua_getlocal( } #[import(lua_getmetatable)] -pub extern "C-unwind" fn lua_getmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int {} +pub extern "C-unwind" fn lua_getmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int { +} #[import(lua_getstack)] pub extern "C-unwind" fn lua_getstack( @@ -143,3 +160,296 @@ pub extern "C-unwind" fn lua_isnumber(lua_state: *mut lua_State, index: c_int) - #[import(lua_isstringornumberconvertabletostring)] pub extern "C-unwind" fn lua_isstring(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_isuserdata)] +pub extern "C-unwind" fn lua_isuserdata(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_len)] +pub extern "C-unwind" fn lua_len(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_load)] +pub extern "C-unwind" fn lua_load( + lua_state: *mut lua_State, + reader: lua_Reader, + data: *mut c_void, + chunk_name: *const c_char, + mode: *const c_char, +) -> c_int { +} + +// lua_newstate + +#[import(lua_newthread)] +pub extern "C-unwind" fn lua_newthread(lua_state: *mut lua_State) -> *mut lua_State {} + +#[import(lua_newuserdata)] +pub extern "C-unwind" fn lua_newuserdata(lua_state: *mut lua_State, size: c_size_t) -> *mut c_void { +} + +#[import(lua_next)] +pub extern "C-unwind" fn lua_next(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_pcallk)] +pub extern "C-unwind" fn lua_pcallk( + lua_state: *mut lua_State, + nargs: c_int, + nresults: c_int, + error_function: c_int, + ctx: c_int, + k: Option, +) -> c_int { +} + +#[import(lua_pushboolean)] +pub extern "C-unwind" fn lua_pushboolean(lua_state: *mut lua_State, b: c_int) {} + +#[import(lua_pushcclosure)] +pub extern "C-unwind" fn lua_pushcclosure(lua_state: *mut lua_State, f: lua_CFunction, n: c_int) {} + +#[import(lua_pushfstring)] +pub extern "C-unwind" fn lua_pushfstring( + lua_state: *mut lua_State, + format: *const c_char, + ... +) -> *const c_char { +} + +#[import(lua_pushinteger)] +pub extern "C-unwind" fn lua_pushinteger(lua_state: *mut lua_State, n: lua_Integer) {} + +#[import(lua_pushlightuserdata)] +pub extern "C-unwind" fn lua_pushlightuserdata(lua_state: *mut lua_State, p: *mut c_void) {} + +#[import(lua_pushlstring)] +pub extern "C-unwind" fn lua_pushlstring( + lua_state: *mut lua_State, + s: *const c_char, + len: c_size_t, +) -> *const c_char { +} + +#[import(lua_pushnil)] +pub extern "C-unwind" fn lua_pushnil(lua_state: *mut lua_State) {} + +#[import(lua_pushnumber)] +pub extern "C-unwind" fn lua_pushnumber(lua_state: *mut lua_State, n: lua_Number) {} + +#[import(lua_pushstring)] +pub extern "C-unwind" fn lua_pushstring( + lua_state: *mut lua_State, + s: *const c_char, +) -> *const c_char { +} + +#[import(lua_pushthread)] +pub extern "C-unwind" fn lua_pushthread(lua_state: *mut lua_State) -> c_int {} + +#[import(lua_pushunsigned)] +pub extern "C-unwind" fn lua_pushunsigned(lua_state: *mut lua_State, number: lua_Unsigned) {} + +#[import(lua_pushvalue)] +pub extern "C-unwind" fn lua_pushvalue(lua_state: *mut lua_State, index: c_int) {} + +// lua_pushvfstring + +#[import(lua_rawequal)] +pub extern "C-unwind" fn lua_rawequal( + lua_state: *mut lua_State, + index_1: c_int, + index_2: c_int, +) -> c_int { +} + +#[import(lua_rawget)] +pub extern "C-unwind" fn lua_rawget(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_rawgeti)] +pub extern "C-unwind" fn lua_rawgeti(lua_state: *mut lua_State, index: c_int, n: c_int) {} + +#[import(lua_rawgetp)] +pub extern "C-unwind" fn lua_rawgetp(lua_state: *mut lua_State, index: c_int, p: *const c_void) {} + +#[import(lua_rawlen)] +pub extern "C-unwind" fn lua_rawlen(lua_state: *mut lua_State, index: c_int) -> c_size_t {} + +#[import(lua_rawset)] +pub extern "C-unwind" fn lua_rawset(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_rawseti)] +pub extern "C-unwind" fn lua_rawseti(lua_state: *mut lua_State, index: c_int, n: c_int) {} + +#[import(lua_rawsetp)] +pub extern "C-unwind" fn lua_rawsetp( + lua_state: *mut lua_State, + index: c_int, + p: *const c_void, +) -> c_void { +} + +#[import(lua_remove)] +pub extern "C-unwind" fn lua_remove(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_replace)] +pub extern "C-unwind" fn lua_replace(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_setallocf)] +pub extern "C-unwind" fn lua_setallocf( + lua_state: *mut lua_State, + f: lua_Alloc, + ud: *mut c_void, +) -> c_void { +} + +#[import(lua_setfield)] +pub extern "C-unwind" fn lua_setfield( + lua_state: *mut lua_State, + index: c_int, + k: *const c_char, +) -> c_void { +} + +#[import(lua_setglobal)] +pub extern "C-unwind" fn lua_setglobal( + lua_state: *mut lua_State, + global_varible_name: *const c_char, +) -> c_void { +} + +#[import(lua_sethook)] +pub extern "C-unwind" fn lua_sethook( + lua_state: *mut lua_State, + hook: Option, + mask: c_int, + count: c_int, +) { +} + +#[import(lua_setlocal)] +pub extern "C-unwind" fn lua_setlocal( + lua_state: *mut lua_State, + ar: *const lua_Debug, + n: c_int, +) -> *const c_char { +} + +#[import(lua_setmetatable)] +pub extern "C-unwind" fn lua_setmetatable(lua_state: *mut lua_State, object_index: c_int) -> c_int { +} + +#[import(lua_settable)] +pub extern "C-unwind" fn lua_settable(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_settop)] +pub extern "C-unwind" fn lua_settop(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_setupvalue)] +pub extern "C-unwind" fn lua_setupvalue( + lua_state: *mut lua_State, + function_index: c_int, + upvalue_index: c_int, +) -> *const c_char { +} + +#[import(lua_setuservalue)] +pub extern "C-unwind" fn lua_setuservalue(lua_state: *mut lua_State, index: c_int) {} + +#[import(lua_status)] +pub extern "C-unwind" fn lua_status(lua_state: *mut lua_State) -> c_int {} + +#[import(lua_toboolean)] +pub extern "C-unwind" fn lua_toboolean(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_tocfunction)] +pub extern "C-unwind" fn lua_tocfunction( + lua_state: *mut lua_State, + index: c_int, +) -> Option { +} + +#[import(lua_tointegerx)] +pub extern "C-unwind" fn lua_tointegerx( + lua_state: *mut lua_State, + index: c_int, + is_num: *mut c_int, +) -> lua_Integer { +} + +#[import(lua_tolstring)] +pub extern "C-unwind" fn lua_tolstring( + lua_state: *mut lua_State, + index: c_int, + len: *mut c_size_t, +) -> *const c_char { +} + +#[import(lua_tonumberx)] +pub extern "C-unwind" fn lua_tonumberx( + lua_state: *mut lua_State, + index: c_int, + is_num: *mut c_int, +) -> lua_Number { +} + +#[import(lua_topointer)] +pub extern "C-unwind" fn lua_topointer( + lua_state: *mut lua_State, + index: c_int, +) -> *const c_void { +} + +#[import(lua_tothread)] +pub extern "C-unwind" fn lua_tothread(lua_state: *mut lua_State, index: c_int) -> *mut lua_State {} + +#[import(lua_tounsignedx)] +pub extern "C-unwind" fn lua_tounsignedx( + lua_state: *mut lua_State, + index: c_int, + is_num: *mut c_int, +) -> lua_Unsigned { +} + +#[import(lua_touserdata)] +pub extern "C-unwind" fn lua_touserdata( + lua_state: *mut lua_State, + index: c_int, +) -> *mut c_void { +} + +#[import(lua_type)] +pub extern "C-unwind" fn lua_type(lua_state: *mut lua_State, index: c_int) -> c_int {} + +#[import(lua_typename)] +pub extern "C-unwind" fn lua_typename( + lua_state: *mut lua_State, + type_: c_int, +) -> *const c_char { +} + +#[import(lua_upvalueid)] +pub extern "C-unwind" fn lua_upvalueid( + lua_state: *mut lua_State, + function_index: c_int, + n: c_int, +) -> *mut c_void { +} + +#[import(lua_upvaluejoin)] +pub extern "C-unwind" fn lua_upvaluejoin( + lua_state: *mut lua_State, + function_index_1: c_int, + n1: c_int, + function_index_2: c_int, + n2: c_int, +) { +} + +#[import(lua_version)] +pub extern "C-unwind" fn lua_version(lua_state: *mut lua_State) -> *const lua_Number {} + +#[import(lua_xmove)] +pub extern "C-unwind" fn lua_xmove( + from: *mut lua_State, + to: *mut lua_State, + n: c_int, +) { +} \ No newline at end of file diff --git a/src/lua/luastate.rs b/src/lua/luastate.rs index 87eee51..5a0c271 100644 --- a/src/lua/luastate.rs +++ b/src/lua/luastate.rs @@ -1,29 +1,45 @@ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_docs)] +use core::ffi::c_size_t; use std::ffi::{ c_char, c_double, c_int, c_longlong, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, }; use std::fmt::Debug; +pub type lua_Number = c_double; +pub type lua_Unsigned = c_uint; +pub type lua_Integer = i64; + +type lu_byte = c_char; +type Instruction = c_uint; // 32 bit +type ptrdiff_t = isize; // https://en.cppreference.com/w/cpp/types/ptrdiff_t +type luai_jmpbuf = c_int; +type lu_mem = c_size_t; +type l_mem = ptrdiff_t; + pub type lua_CFunction = unsafe extern "C-unwind" fn(L: *mut lua_State) -> c_int; + pub type lua_Hook = unsafe extern "C-unwind" fn(L: *mut lua_State, ar: *mut lua_Debug); + pub type lua_Alloc = unsafe extern "C-unwind" fn( ud: *mut c_void, ptr: *mut c_void, osize: usize, nsize: usize, ) -> *mut c_void; -pub type lua_Writer = - unsafe extern "C-unwind" fn(L: *mut lua_State, p: *const c_void, sz: usize, ud: *mut c_void) -> c_int; -type size_t = c_ulong; // c_size_t is nightly only, defaults to usize currently -> 64 bit -type lu_byte = c_char; -type lua_Number = c_double; -type Instruction = c_uint; // 32 bit -type ptrdiff_t = isize; // https://en.cppreference.com/w/cpp/types/ptrdiff_t -type luai_jmpbuf = c_int; -type lu_mem = size_t; -type l_mem = ptrdiff_t; +pub type lua_Writer = unsafe extern "C-unwind" fn( + L: *mut lua_State, + p: *const c_void, + sz: usize, + ud: *mut c_void, +) -> c_int; + +pub type lua_Reader = unsafe extern "C-unwind" fn( + L: *mut lua_State, + ud: *mut c_void, + sz: *mut c_size_t, +) -> *const c_char; #[derive(Clone, Copy, Debug)] #[repr(C)] @@ -60,7 +76,7 @@ pub struct TStringInner { // common header extra: lu_byte, hash: c_uint, - len: size_t, + len: c_size_t, } #[derive(Clone, Copy)] @@ -380,8 +396,8 @@ pub struct lua_State { #[repr(C)] pub struct Mbuffer { buffer: *mut c_char, - n: size_t, - buffsize: size_t, + n: c_size_t, + buffsize: c_size_t, } #[derive(Clone, Copy, Debug)] From b22925b904be0c6d78084d8d273c7860bae03e72 Mon Sep 17 00:00:00 2001 From: notnotmelon Date: Thu, 22 Aug 2024 13:02:16 -0500 Subject: [PATCH 4/4] chore: cargo fmt --- src/lua/luac_interface.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/lua/luac_interface.rs b/src/lua/luac_interface.rs index 1d2b3af..7521cb6 100644 --- a/src/lua/luac_interface.rs +++ b/src/lua/luac_interface.rs @@ -391,11 +391,7 @@ pub extern "C-unwind" fn lua_tonumberx( } #[import(lua_topointer)] -pub extern "C-unwind" fn lua_topointer( - lua_state: *mut lua_State, - index: c_int, -) -> *const c_void { -} +pub extern "C-unwind" fn lua_topointer(lua_state: *mut lua_State, index: c_int) -> *const c_void {} #[import(lua_tothread)] pub extern "C-unwind" fn lua_tothread(lua_state: *mut lua_State, index: c_int) -> *mut lua_State {} @@ -409,21 +405,13 @@ pub extern "C-unwind" fn lua_tounsignedx( } #[import(lua_touserdata)] -pub extern "C-unwind" fn lua_touserdata( - lua_state: *mut lua_State, - index: c_int, -) -> *mut c_void { -} +pub extern "C-unwind" fn lua_touserdata(lua_state: *mut lua_State, index: c_int) -> *mut c_void {} #[import(lua_type)] pub extern "C-unwind" fn lua_type(lua_state: *mut lua_State, index: c_int) -> c_int {} #[import(lua_typename)] -pub extern "C-unwind" fn lua_typename( - lua_state: *mut lua_State, - type_: c_int, -) -> *const c_char { -} +pub extern "C-unwind" fn lua_typename(lua_state: *mut lua_State, type_: c_int) -> *const c_char {} #[import(lua_upvalueid)] pub extern "C-unwind" fn lua_upvalueid( @@ -447,9 +435,4 @@ pub extern "C-unwind" fn lua_upvaluejoin( pub extern "C-unwind" fn lua_version(lua_state: *mut lua_State) -> *const lua_Number {} #[import(lua_xmove)] -pub extern "C-unwind" fn lua_xmove( - from: *mut lua_State, - to: *mut lua_State, - n: c_int, -) { -} \ No newline at end of file +pub extern "C-unwind" fn lua_xmove(from: *mut lua_State, to: *mut lua_State, n: c_int) {}