diff --git a/crates/lune-std-ffi/README.md b/crates/lune-std-ffi/README.md index 1b8c6ca..05a98ee 100644 --- a/crates/lune-std-ffi/README.md +++ b/crates/lune-std-ffi/README.md @@ -9,7 +9,7 @@ Define C-ABI type information and provide conversion and casting - [**Struct ` CArrInfo`:**](./src/c/struct_info.rs) Represents C Array type - [**Struct ` CPtrInfo`:**](./src/c/ptr_info.rs) Represents C Pointer type - [**Struct ` CFnInfo`:**](./src/c/fn_info.rs) Represents C Function signature - provide CallableData and ClosureData creation + > provide CallableData and ClosureData creation - [**Struct ` CStructInfo`:**](./src/c/struct_info.rs) Represents C Struct type - [**Struct ` CTypeInfo`:**](./src/c/type_info.rs) Represents C type, extended in `/c/types` @@ -55,6 +55,11 @@ Implememt type-casting for all CTypes - **Trait `FfiSignedness`** - **Trait `FfiConvert`:** Provide read LuaValue from FfiData or write LuaValue into FfiData +**Traits:** Provide call information trait + +- **Trait `FfiArg`:** Used for argument boundary checking and callback argument ref flag +- **Trait `FfiResult`:** Used for result boundary checking + **Trait `FfiData`:** Provide common data handle, including methods below - **Method `check_boundary`:** check boundary with offset and size @@ -66,14 +71,22 @@ Implememt type-casting for all CTypes **Mods:** Provide common helper functions -- **`association.rs`:** GC utility, used for inner, ret and arg type holding in subtype -- **`bit_mask.rs`:** u8 bitfield helper -- **`cast.rs`:** library +- [**Mod `association.rs`:**](./src/ffi/association.rs) GC utility, used for inner, ret and arg type holding in subtype +- [**Mod `bit_mask.rs`:**](./src/ffi/bit_mask.rs) u8 bitfield helper +- [**Mod `cast.rs`:**](./src/ffi/cast.rs) library - **Function `num_cast(from: FfiData, from: FfiData)`:** Cast number type value inno another number type -- **`libffi_helper.rs`:** +- [**Mod `libffi_helper.rs`:**](./src/ffi/libffi_helper.rs) - **Const `FFI_STATUS_NAMES`:** Used for ffi_status stringify - **Function `get_ensured_size`:** Returns ensured ffi_type size - **Const `SIEE_OF_POINTER`:** Platform specific pointer size (Compile time known) ## TODO + +Add `CTypeInfo:add(target, from1, from2, ...)` and `:sub` `:mul` `:div` `:mod` `:pow` for math operation. + +> Luau cannot handle i64 or i128 + +Add bor band and such bit-related operation + +> Luau only supports 32bit bit operations diff --git a/crates/lune-std-ffi/src/c/arr_info.rs b/crates/lune-std-ffi/src/c/arr_info.rs index 088fe34..16d3d0c 100644 --- a/crates/lune-std-ffi/src/c/arr_info.rs +++ b/crates/lune-std-ffi/src/c/arr_info.rs @@ -4,10 +4,7 @@ use libffi::middle::Type; use mlua::prelude::*; use super::{association_names::CARR_INNER, helper, method_provider}; -use crate::{ - data::{FfiConvert, FfiData, FfiSize}, - ffi::{association, libffi_helper::get_ensured_size}, -}; +use crate::ffi::{association, libffi_helper::get_ensured_size, FfiConvert, FfiData, FfiSize}; // This is a series of some type. // It provides the final size and the offset of the index, diff --git a/crates/lune-std-ffi/src/c/fn_info.rs b/crates/lune-std-ffi/src/c/fn_info.rs index b2942a4..146d6fa 100644 --- a/crates/lune-std-ffi/src/c/fn_info.rs +++ b/crates/lune-std-ffi/src/c/fn_info.rs @@ -4,12 +4,15 @@ use libffi::middle::{Cif, Type}; use mlua::prelude::*; use super::{ - association_names::{CALLABLE_CFN, CALLABLE_REF, CFN_ARGS, CFN_RESULT}, - helper, method_provider, + association_names::{ + CALLABLE_CFN, CALLABLE_REF, CFN_ARGS, CFN_RESULT, CLOSURE_CFN, CLOSURE_FUNC, + }, + ctype_helper::is_ctype, + helper, method_provider, CArrInfo, CPtrInfo, CStructInfo, }; use crate::{ - data::{CallableData, RefData, RefDataFlag}, - ffi::{association, bit_mask::*, FfiArgInfo, FfiData, FfiResultInfo, FfiSignedness, FfiSize}, + data::{CallableData, ClosureData, RefData, RefFlag}, + ffi::{association, bit_mask::*, FfiArg, FfiData, FfiResult, FfiSignedness, FfiSize}, }; // cfn is a type declaration for a function. @@ -30,8 +33,8 @@ use crate::{ pub struct CFnInfo { cif: Cif, - arg_info_list: Vec, - result_info: FfiResultInfo, + arg_info_list: Vec, + result_info: FfiResult, } impl FfiSignedness for CFnInfo { @@ -45,15 +48,39 @@ impl FfiSize for CFnInfo { } } +const CALLBACK_ARG_REF_FLAG_TYPE: u8 = RefFlag::Readable.value(); +const CALLBACK_ARG_REF_FLAG_PTR: u8 = RefFlag::Dereferenceable.value() | RefFlag::Readable.value(); +const CALLBACK_ARG_REF_FLAG_ARR: u8 = RefFlag::Readable.value() | RefFlag::Offsetable.value(); +const CALLBACK_ARG_REF_FLAG_STRUCT: u8 = RefFlag::Readable.value() | RefFlag::Offsetable.value(); +const CALLBACK_ARG_REF_FLAG_CFN: u8 = RefFlag::Function.value(); + +fn create_arg_info(userdata: &LuaAnyUserData) -> LuaResult { + let callback_ref_flag = if is_ctype(userdata) { + CALLBACK_ARG_REF_FLAG_TYPE + } else if userdata.is::() { + CALLBACK_ARG_REF_FLAG_PTR + } else if userdata.is::() { + CALLBACK_ARG_REF_FLAG_ARR + } else if userdata.is::() { + CALLBACK_ARG_REF_FLAG_STRUCT + } else if userdata.is::() { + CALLBACK_ARG_REF_FLAG_CFN + } else { + return Err(LuaError::external("unexpected type userdata")); + }; + Ok(FfiArg { + size: helper::get_size(userdata)?, + callback_ref_flag, + }) +} + impl CFnInfo { pub fn new( args: Vec, ret: Type, - arg_info_list: Vec, - result_info: FfiResultInfo, + arg_info_list: Vec, + result_info: FfiResult, ) -> LuaResult { - // let cif = ; - Ok(Self { cif: Cif::new(args.clone(), ret.clone()), arg_info_list, @@ -61,7 +88,7 @@ impl CFnInfo { }) } - pub fn new_from_table<'lua>( + pub fn from_table<'lua>( lua: &'lua Lua, arg_table: LuaTable, ret: LuaAnyUserData, @@ -70,16 +97,12 @@ impl CFnInfo { let ret_type = helper::get_middle_type(&ret)?; let arg_len = arg_table.raw_len(); - let mut arg_info_list = Vec::::with_capacity(arg_len); + let mut arg_info_list = Vec::::with_capacity(arg_len); for index in 0..arg_len { let userdata = helper::get_userdata(arg_table.raw_get(index + 1)?)?; - arg_info_list.push(FfiArgInfo { - conv: unsafe { helper::get_conv(&userdata)? }, - size: helper::get_size(&userdata)?, - }); + arg_info_list.push(create_arg_info(&userdata)?); } - let result_info = FfiResultInfo { - conv: unsafe { helper::get_conv(&ret)? }, + let result_info = FfiResult { size: helper::get_size(&ret)?, }; @@ -122,6 +145,57 @@ impl CFnInfo { Err(LuaError::external("failed to get inner type userdata.")) } } + + pub fn create_closure<'lua>( + &self, + lua: &'lua Lua, + this: &LuaAnyUserData, + lua_function: LuaFunction<'lua>, + ) -> LuaResult> { + let closure = ClosureData::new( + ptr::from_ref(lua), + self.cif.as_raw_ptr(), + self.arg_info_list.clone(), + self.result_info.clone(), + lua.create_registry_value(&lua_function)?, + )?; + let closure_userdata = lua.create_userdata(closure)?; + + association::set(lua, CLOSURE_CFN, &closure_userdata, this)?; + association::set(lua, CLOSURE_FUNC, &closure_userdata, lua_function)?; + + Ok(closure_userdata) + } + + pub fn create_callable<'lua>( + &self, + lua: &'lua Lua, + this: &LuaAnyUserData, + target_ref: &LuaAnyUserData, + ) -> LuaResult> { + if !target_ref.is::() { + return Err(LuaError::external("argument 0 must be ffiref")); + } + + let ffi_ref = target_ref.borrow::()?; + if u8_test_not(ffi_ref.flags, RefFlag::Function.value()) { + return Err(LuaError::external("not a function ref")); + } + + let callable = lua.create_userdata(unsafe { + CallableData::new( + self.cif.as_raw_ptr(), + self.arg_info_list.clone(), + self.result_info.clone(), + ffi_ref.get_pointer(), + ) + })?; + + association::set(lua, CALLABLE_CFN, &callable, this)?; + association::set(lua, CALLABLE_REF, &callable, target_ref)?; + + Ok(callable) + } } impl LuaUserData for CFnInfo { @@ -134,36 +208,18 @@ impl LuaUserData for CFnInfo { method_provider::provide_to_string(methods); // Realize - // methods.add_method("closure", |lua, this, func: LuaFunction| { - // lua.create_userdata(FfiClosure::new(this.cif, userdata)) - // }) + methods.add_function( + "closure", + |lua, (cfn, func): (LuaAnyUserData, LuaFunction)| { + let this = cfn.borrow::()?; + this.create_closure(lua, cfn.as_ref(), func) + }, + ); methods.add_function( "callable", - |lua, (cfn, function_ref): (LuaAnyUserData, LuaAnyUserData)| { + |lua, (cfn, target): (LuaAnyUserData, LuaAnyUserData)| { let this = cfn.borrow::()?; - - if !function_ref.is::() { - return Err(LuaError::external("argument 0 must be ffiref")); - } - - let ffi_ref = function_ref.borrow::()?; - if u8_test_not(ffi_ref.flags, RefDataFlag::Function.value()) { - return Err(LuaError::external("not a function ref")); - } - - let callable = lua.create_userdata(unsafe { - CallableData::new( - this.cif.as_raw_ptr(), - ptr::from_ref(&this.arg_info_list), - ptr::from_ref(&this.result_info), - ffi_ref.get_pointer(), - ) - })?; - - association::set(lua, CALLABLE_CFN, &callable, cfn.clone())?; - association::set(lua, CALLABLE_REF, &callable, function_ref.clone())?; - - Ok(callable) + this.create_callable(lua, cfn.as_ref(), &target) }, ); } diff --git a/crates/lune-std-ffi/src/c/helper.rs b/crates/lune-std-ffi/src/c/helper.rs index 7f7b5ae..04465ab 100644 --- a/crates/lune-std-ffi/src/c/helper.rs +++ b/crates/lune-std-ffi/src/c/helper.rs @@ -3,7 +3,10 @@ use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; use mlua::prelude::*; use super::{ctype_helper, CArrInfo, CFnInfo, CPtrInfo, CStructInfo}; -use crate::data::{BoxData, FfiConvert, FfiSize, GetFfiData}; +use crate::{ + data::{BoxData, GetFfiData}, + ffi::{FfiConvert, FfiSize}, +}; pub mod method_provider { use super::*; diff --git a/crates/lune-std-ffi/src/c/mod.rs b/crates/lune-std-ffi/src/c/mod.rs index 075c886..ad5b8f1 100644 --- a/crates/lune-std-ffi/src/c/mod.rs +++ b/crates/lune-std-ffi/src/c/mod.rs @@ -25,4 +25,6 @@ mod association_names { pub const CFN_ARGS: &str = "__cfn_args"; pub const CALLABLE_REF: &str = "__callable_ref"; pub const CALLABLE_CFN: &str = "__callable_cfn"; + pub const CLOSURE_FUNC: &str = "__closure_func"; + pub const CLOSURE_CFN: &str = "__closure_cfn"; } diff --git a/crates/lune-std-ffi/src/c/ptr_info.rs b/crates/lune-std-ffi/src/c/ptr_info.rs index 4383da8..d34d44e 100644 --- a/crates/lune-std-ffi/src/c/ptr_info.rs +++ b/crates/lune-std-ffi/src/c/ptr_info.rs @@ -5,8 +5,10 @@ use mlua::prelude::*; use super::{association_names::CPTR_INNER, ctype_helper, helper, method_provider}; use crate::{ - data::{FfiConvert, FfiData, FfiSignedness, FfiSize, RefData}, - ffi::{association, libffi_helper::SIEE_OF_POINTER}, + data::RefData, + ffi::{ + association, libffi_helper::SIZE_OF_POINTER, FfiConvert, FfiData, FfiSignedness, FfiSize, + }, }; pub struct CPtrInfo { @@ -20,7 +22,7 @@ impl FfiSignedness for CPtrInfo { } impl FfiSize for CPtrInfo { fn get_size(&self) -> usize { - SIEE_OF_POINTER + SIZE_OF_POINTER } } impl FfiConvert for CPtrInfo { diff --git a/crates/lune-std-ffi/src/c/struct_info.rs b/crates/lune-std-ffi/src/c/struct_info.rs index dd3d55f..4c67fcc 100644 --- a/crates/lune-std-ffi/src/c/struct_info.rs +++ b/crates/lune-std-ffi/src/c/struct_info.rs @@ -4,9 +4,8 @@ use libffi::{low, middle::Type, raw}; use mlua::prelude::*; use super::{association_names::CSTRUCT_INNER, helper, method_provider}; -use crate::{ - data::{FfiConvert, FfiData, FfiSignedness, FfiSize}, - ffi::{association, libffi_helper::FFI_STATUS_NAMES}, +use crate::ffi::{ + association, libffi_helper::FFI_STATUS_NAMES, FfiConvert, FfiData, FfiSignedness, FfiSize, }; pub struct CStructInfo { diff --git a/crates/lune-std-ffi/src/c/type_info.rs b/crates/lune-std-ffi/src/c/type_info.rs index dd459e8..53cb879 100644 --- a/crates/lune-std-ffi/src/c/type_info.rs +++ b/crates/lune-std-ffi/src/c/type_info.rs @@ -8,8 +8,8 @@ use mlua::prelude::*; use super::method_provider; use crate::{ - data::{FfiConvert, FfiData, FfiSignedness, FfiSize, GetFfiData}, - ffi::libffi_helper::get_ensured_size, + data::GetFfiData, + ffi::{libffi_helper::get_ensured_size, FfiConvert, FfiData, FfiSignedness, FfiSize}, }; // Cast native data diff --git a/crates/lune-std-ffi/src/c/types/f32.rs b/crates/lune-std-ffi/src/c/types/f32.rs index f397433..434c981 100644 --- a/crates/lune-std-ffi/src/c/types/f32.rs +++ b/crates/lune-std-ffi/src/c/types/f32.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/f64.rs b/crates/lune-std-ffi/src/c/types/f64.rs index 1055c5c..dd59a89 100644 --- a/crates/lune-std-ffi/src/c/types/f64.rs +++ b/crates/lune-std-ffi/src/c/types/f64.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/i128.rs b/crates/lune-std-ffi/src/c/types/i128.rs index 6a0b55c..2c51f79 100644 --- a/crates/lune-std-ffi/src/c/types/i128.rs +++ b/crates/lune-std-ffi/src/c/types/i128.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/i16.rs b/crates/lune-std-ffi/src/c/types/i16.rs index a6c2948..077eb2a 100644 --- a/crates/lune-std-ffi/src/c/types/i16.rs +++ b/crates/lune-std-ffi/src/c/types/i16.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/i32.rs b/crates/lune-std-ffi/src/c/types/i32.rs index 8afd129..bfdf543 100644 --- a/crates/lune-std-ffi/src/c/types/i32.rs +++ b/crates/lune-std-ffi/src/c/types/i32.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/i64.rs b/crates/lune-std-ffi/src/c/types/i64.rs index f4f914f..1dea347 100644 --- a/crates/lune-std-ffi/src/c/types/i64.rs +++ b/crates/lune-std-ffi/src/c/types/i64.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/i8.rs b/crates/lune-std-ffi/src/c/types/i8.rs index 53ec853..6ac64ff 100644 --- a/crates/lune-std-ffi/src/c/types/i8.rs +++ b/crates/lune-std-ffi/src/c/types/i8.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/isize.rs b/crates/lune-std-ffi/src/c/types/isize.rs index ccd5405..d1fda6c 100644 --- a/crates/lune-std-ffi/src/c/types/isize.rs +++ b/crates/lune-std-ffi/src/c/types/isize.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/mod.rs b/crates/lune-std-ffi/src/c/types/mod.rs index 0e0387e..6d4169f 100644 --- a/crates/lune-std-ffi/src/c/types/mod.rs +++ b/crates/lune-std-ffi/src/c/types/mod.rs @@ -8,7 +8,7 @@ use mlua::prelude::*; use num::cast::AsPrimitive; use super::{CTypeCast, CTypeInfo}; -use crate::data::{num_cast, FfiConvert, FfiData, FfiSize}; +use crate::ffi::{num_cast, FfiConvert, FfiData, FfiSize}; pub mod f32; pub mod f64; diff --git a/crates/lune-std-ffi/src/c/types/u128.rs b/crates/lune-std-ffi/src/c/types/u128.rs index 34af1e5..a22ce8f 100644 --- a/crates/lune-std-ffi/src/c/types/u128.rs +++ b/crates/lune-std-ffi/src/c/types/u128.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/u16.rs b/crates/lune-std-ffi/src/c/types/u16.rs index b342834..c6946c6 100644 --- a/crates/lune-std-ffi/src/c/types/u16.rs +++ b/crates/lune-std-ffi/src/c/types/u16.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/u32.rs b/crates/lune-std-ffi/src/c/types/u32.rs index 09d9a07..b63b67f 100644 --- a/crates/lune-std-ffi/src/c/types/u32.rs +++ b/crates/lune-std-ffi/src/c/types/u32.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/u64.rs b/crates/lune-std-ffi/src/c/types/u64.rs index beb1ba4..ff90b76 100644 --- a/crates/lune-std-ffi/src/c/types/u64.rs +++ b/crates/lune-std-ffi/src/c/types/u64.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/u8.rs b/crates/lune-std-ffi/src/c/types/u8.rs index a7d9ad3..3278579 100644 --- a/crates/lune-std-ffi/src/c/types/u8.rs +++ b/crates/lune-std-ffi/src/c/types/u8.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/c/types/usize.rs b/crates/lune-std-ffi/src/c/types/usize.rs index 0fa4442..1d7d0f4 100644 --- a/crates/lune-std-ffi/src/c/types/usize.rs +++ b/crates/lune-std-ffi/src/c/types/usize.rs @@ -5,7 +5,7 @@ use num::cast::AsPrimitive; use crate::{ c::type_info::CTypeInfo, - data::{FfiConvert, FfiData, FfiSignedness}, + ffi::{FfiConvert, FfiData, FfiSignedness}, }; impl FfiSignedness for CTypeInfo { diff --git a/crates/lune-std-ffi/src/data/box_data/flag.rs b/crates/lune-std-ffi/src/data/box_data/flag.rs index f54a1b5..181326c 100644 --- a/crates/lune-std-ffi/src/data/box_data/flag.rs +++ b/crates/lune-std-ffi/src/data/box_data/flag.rs @@ -1,10 +1,10 @@ use crate::ffi::bit_mask::*; -pub enum BoxDataFlag { +pub enum BoxFlag { Leaked, } -impl BoxDataFlag { +impl BoxFlag { pub const fn value(&self) -> u8 { match self { Self::Leaked => U8_MASK2, diff --git a/crates/lune-std-ffi/src/data/box_data/mod.rs b/crates/lune-std-ffi/src/data/box_data/mod.rs index ea5b1f4..97ee9e1 100644 --- a/crates/lune-std-ffi/src/data/box_data/mod.rs +++ b/crates/lune-std-ffi/src/data/box_data/mod.rs @@ -3,17 +3,17 @@ use std::{alloc, alloc::Layout, boxed::Box, mem::ManuallyDrop, ptr}; use mlua::prelude::*; use crate::{ - data::{association_names::REF_INNER, RefData, RefDataBounds, RefDataFlag}, + data::{association_names::REF_INNER, RefBounds, RefData, RefFlag}, ffi::{association, bit_mask::*, FfiData}, }; mod flag; -pub use self::flag::BoxDataFlag; +pub use self::flag::BoxFlag; // Ref which created by lua should not be dereferenceable, const BOX_REF_FLAGS: u8 = - RefDataFlag::Readable.value() | RefDataFlag::Writable.value() | RefDataFlag::Offsetable.value(); + RefFlag::Readable.value() | RefFlag::Writable.value() | RefFlag::Offsetable.value(); // It is an untyped, sized memory area that Lua can manage. // This area is safe within Lua. Operations have their boundaries checked. @@ -63,7 +63,7 @@ impl BoxData { } pub fn leak(&mut self) { - self.flags = u8_set(self.flags, BoxDataFlag::Leaked.value(), true); + self.flags = u8_set(self.flags, BoxFlag::Leaked.value(), true); } // Make FfiRef from box, with boundary checking @@ -73,7 +73,7 @@ impl BoxData { offset: Option, ) -> LuaResult> { let target = this.borrow::()?; - let mut bounds = RefDataBounds::new(0, target.size()); + let mut bounds = RefBounds::new(0, target.size()); let mut ptr = unsafe { target.get_pointer() }; // Calculate offset @@ -114,7 +114,7 @@ impl BoxData { impl Drop for BoxData { fn drop(&mut self) { - if u8_test_not(self.flags, BoxDataFlag::Leaked.value()) { + if u8_test_not(self.flags, BoxFlag::Leaked.value()) { unsafe { self.drop() }; } } diff --git a/crates/lune-std-ffi/src/data/callable_data.rs b/crates/lune-std-ffi/src/data/callable_data.rs index ca8f65c..001ef7a 100644 --- a/crates/lune-std-ffi/src/data/callable_data.rs +++ b/crates/lune-std-ffi/src/data/callable_data.rs @@ -7,20 +7,21 @@ use libffi::{ }; use mlua::prelude::*; -use super::{FfiArgInfo, FfiData, FfiResultInfo, GetFfiData}; +use super::{FfiData, GetFfiData}; +use crate::ffi::{FfiArg, FfiResult}; pub struct CallableData { cif: *mut ffi_cif, - arg_info_list: *const Vec, - result_info: *const FfiResultInfo, + arg_info_list: Vec, + result_info: FfiResult, code: CodePtr, } impl CallableData { pub unsafe fn new( cif: *mut ffi_cif, - arg_info_list: *const Vec, - result_info: *const FfiResultInfo, + arg_info_list: Vec, + result_info: FfiResult, function_pointer: *const (), ) -> Self { Self { @@ -35,16 +36,15 @@ impl CallableData { pub unsafe fn call(&self, result: &Ref, args: LuaMultiValue) -> LuaResult<()> { result - .check_boundary(0, self.result_info.as_ref().unwrap().size) + .check_boundary(0, self.result_info.size) .then_some(()) .ok_or_else(|| LuaError::external("result boundary check failed"))?; // cache Vec => unable to create async call but no allocation - let arg_info_list = self.arg_info_list.as_ref().unwrap(); - let mut arg_list = Vec::<*mut c_void>::with_capacity(arg_info_list.len()); + let mut arg_list = Vec::<*mut c_void>::with_capacity(self.arg_info_list.len()); - for index in 0..arg_info_list.len() { - let arg_info = arg_info_list.get(index).unwrap(); + for index in 0..self.arg_info_list.len() { + let arg_info = self.arg_info_list.get(index).unwrap(); let arg = args .get(index) .ok_or_else(|| LuaError::external(format!("argument {index} required")))?; diff --git a/crates/lune-std-ffi/src/data/closure_data.rs b/crates/lune-std-ffi/src/data/closure_data.rs index 8175be3..93eece3 100644 --- a/crates/lune-std-ffi/src/data/closure_data.rs +++ b/crates/lune-std-ffi/src/data/closure_data.rs @@ -1,5 +1,5 @@ use core::ffi::c_void; -use std::ptr; +use std::{borrow::Borrow, ptr}; use libffi::{ low::{closure_alloc, closure_free, ffi_cif, CodePtr}, @@ -7,19 +7,22 @@ use libffi::{ }; use mlua::prelude::*; -use super::{ - ref_data::{RefDataBounds, RefDataFlag}, - RefData, +use super::ref_data::{RefBounds, RefData, RefFlag}; +use crate::ffi::{ + libffi_helper::{FFI_STATUS_NAMES, SIZE_OF_POINTER}, + FfiArg, FfiData, FfiResult, }; -use crate::ffi::libffi_helper::FFI_STATUS_NAMES; -pub struct ClosureData<'a> { +pub struct ClosureData { + lua: *const Lua, closure: *mut ffi_closure, code: CodePtr, - userdata: CallbackUserdata<'a>, + arg_info_list: Vec, + result_info: FfiResult, + func: LuaRegistryKey, } -impl<'a> Drop for ClosureData<'a> { +impl Drop for ClosureData { fn drop(&mut self) { unsafe { closure_free(self.closure); @@ -27,69 +30,82 @@ impl<'a> Drop for ClosureData<'a> { } } -#[allow(unused)] -pub struct CallbackUserdata<'a> { - pub func: LuaFunction<'a>, - pub lua: &'a Lua, - pub arg_ref_flags: Vec, - pub arg_ref_size: Vec, - pub result_size: usize, -} - -const RESULT_REF_FLAGS: u8 = RefDataFlag::Leaked.value() | RefDataFlag::Writable.value(); +const RESULT_REF_FLAGS: u8 = + RefFlag::Leaked.value() | RefFlag::Writable.value() | RefFlag::Offsetable.value(); unsafe extern "C" fn callback( cif: *mut ffi_cif, result_pointer: *mut c_void, arg_pointers: *mut *mut c_void, - userdata: *mut c_void, + closure_data: *mut c_void, ) { - let userdata = userdata.cast::(); + let closure_data = closure_data.cast::().as_ref().unwrap(); + let lua = closure_data.lua.as_ref().unwrap(); let len = (*cif).nargs as usize; let mut args = Vec::::with_capacity(len + 1); // Push result pointer (ref) args.push(LuaValue::UserData( - (*userdata) - .lua - .create_userdata(RefData::new( - result_pointer.cast::<()>(), - RESULT_REF_FLAGS, - RefDataBounds::new(0, (*userdata).result_size), - )) - .unwrap(), + lua.create_userdata(RefData::new( + result_pointer.cast::<()>(), + RESULT_REF_FLAGS, + RefBounds::new(0, closure_data.result_info.size), + )) + .unwrap(), )); // Push arg pointer (ref) for i in 0..len { + let arg_info = closure_data.arg_info_list.get(i).unwrap(); args.push(LuaValue::UserData( - (*userdata) - .lua - .create_userdata(RefData::new( - (*arg_pointers.add(i)).cast::<()>(), - (*userdata).arg_ref_flags.get(i).unwrap().to_owned(), - RefDataBounds::new(0, (*userdata).arg_ref_size.get(i).unwrap().to_owned()), - )) - .unwrap(), + lua.create_userdata(RefData::new( + (*arg_pointers.add(i)).cast::<()>(), + arg_info.callback_ref_flag, + RefBounds::new(0, arg_info.size), + )) + .unwrap(), )); } - (*userdata).func.call::<_, ()>(args).unwrap(); + closure_data + .func + .borrow() + .into_lua(lua) + .unwrap() + .as_function() + .unwrap() + .call::<_, ()>(args) + .unwrap(); } -impl<'a> ClosureData<'a> { - pub unsafe fn new( +impl ClosureData { + pub fn new( + lua: *const Lua, cif: *mut ffi_cif, - userdata: CallbackUserdata<'a>, - ) -> LuaResult> { + arg_info_list: Vec, + result_info: FfiResult, + func: LuaRegistryKey, + ) -> LuaResult { let (closure, code) = closure_alloc(); - let prep_result = ffi_prep_closure_loc( + + let closure_data = ClosureData { + lua, closure, - cif, - Some(callback), - ptr::from_ref(&userdata).cast::().cast_mut(), - code.as_mut_ptr(), - ); + code, + arg_info_list, + result_info, + func, + }; + + let prep_result = unsafe { + ffi_prep_closure_loc( + closure, + cif, + Some(callback), + ptr::from_ref(&closure_data).cast::().cast_mut(), + code.as_mut_ptr(), + ) + }; if prep_result != 0 { Err(LuaError::external(format!( @@ -97,11 +113,24 @@ impl<'a> ClosureData<'a> { FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[prep_result as usize] ))) } else { - Ok(ClosureData { - closure, - code, - userdata, - }) + Ok(closure_data) } } } + +impl FfiData for ClosureData { + unsafe fn get_pointer(&self) -> *mut () { + self.code.as_mut_ptr().cast::<()>() + } + fn check_boundary(&self, offset: isize, size: usize) -> bool { + (offset as usize) + size <= SIZE_OF_POINTER + } + fn is_readable(&self) -> bool { + false + } + fn is_writable(&self) -> bool { + false + } +} + +impl LuaUserData for ClosureData {} diff --git a/crates/lune-std-ffi/src/data/lib_data.rs b/crates/lune-std-ffi/src/data/lib_data.rs index 211dbda..a7d38a4 100644 --- a/crates/lune-std-ffi/src/data/lib_data.rs +++ b/crates/lune-std-ffi/src/data/lib_data.rs @@ -2,15 +2,15 @@ use dlopen2::raw::Library; use mlua::prelude::*; use super::{ - association, association_names::SYM_INNER, - ref_data::{RefData, RefDataFlag, UNSIZED_BOUNDS}, + ref_data::{RefData, RefFlag, UNSIZED_BOUNDS}, }; +use crate::ffi::association; -const LIB_REF_FLAGS: u8 = RefDataFlag::Offsetable.value() - | RefDataFlag::Readable.value() - | RefDataFlag::Dereferenceable.value() - | RefDataFlag::Function.value(); +const LIB_REF_FLAGS: u8 = RefFlag::Offsetable.value() + | RefFlag::Readable.value() + | RefFlag::Dereferenceable.value() + | RefFlag::Function.value(); pub struct LibData(Library); diff --git a/crates/lune-std-ffi/src/data/mod.rs b/crates/lune-std-ffi/src/data/mod.rs index 6b5de23..c2ddf5b 100644 --- a/crates/lune-std-ffi/src/data/mod.rs +++ b/crates/lune-std-ffi/src/data/mod.rs @@ -9,19 +9,14 @@ mod closure_data; mod lib_data; mod ref_data; -pub use crate::{ - data::{ - box_data::BoxData, - callable_data::CallableData, - closure_data::ClosureData, - lib_data::LibData, - ref_data::{create_nullptr, RefData, RefDataBounds, RefDataFlag}, - }, - ffi::{ - association, num_cast, FfiArgInfo, FfiConvert, FfiData, FfiResultInfo, FfiSignedness, - FfiSize, - }, +pub use self::{ + box_data::BoxData, + callable_data::CallableData, + closure_data::ClosureData, + lib_data::LibData, + ref_data::{create_nullptr, RefBounds, RefData, RefFlag}, }; +use crate::ffi::FfiData; // Named registry table names mod association_names { diff --git a/crates/lune-std-ffi/src/data/ref_data/bounds.rs b/crates/lune-std-ffi/src/data/ref_data/bounds.rs index cfa1699..6d43491 100644 --- a/crates/lune-std-ffi/src/data/ref_data/bounds.rs +++ b/crates/lune-std-ffi/src/data/ref_data/bounds.rs @@ -1,17 +1,17 @@ // Memory range for ref or box data. For boundary checking -pub struct RefDataBounds { +pub struct RefBounds { // Indicates how much data is above the pointer pub(crate) above: usize, // Indicates how much data is below the pointer pub(crate) below: usize, } -pub const UNSIZED_BOUNDS: RefDataBounds = RefDataBounds { +pub const UNSIZED_BOUNDS: RefBounds = RefBounds { above: usize::MAX, below: usize::MAX, }; -impl RefDataBounds { +impl RefBounds { pub fn new(above: usize, below: usize) -> Self { Self { above, below } } @@ -88,7 +88,7 @@ impl RefDataBounds { } } -impl Clone for RefDataBounds { +impl Clone for RefBounds { fn clone(&self) -> Self { Self { above: self.above, diff --git a/crates/lune-std-ffi/src/data/ref_data/flag.rs b/crates/lune-std-ffi/src/data/ref_data/flag.rs index 3cf3b11..972431d 100644 --- a/crates/lune-std-ffi/src/data/ref_data/flag.rs +++ b/crates/lune-std-ffi/src/data/ref_data/flag.rs @@ -1,6 +1,6 @@ use crate::ffi::bit_mask::*; -pub enum RefDataFlag { +pub enum RefFlag { Leaked, Dereferenceable, Readable, @@ -9,7 +9,7 @@ pub enum RefDataFlag { Function, Uninit, } -impl RefDataFlag { +impl RefFlag { pub const fn value(&self) -> u8 { match self { Self::Leaked => U8_MASK1, diff --git a/crates/lune-std-ffi/src/data/ref_data/mod.rs b/crates/lune-std-ffi/src/data/ref_data/mod.rs index 4659cef..b9a4cb6 100644 --- a/crates/lune-std-ffi/src/data/ref_data/mod.rs +++ b/crates/lune-std-ffi/src/data/ref_data/mod.rs @@ -11,13 +11,13 @@ mod bounds; mod flag; pub use self::{ - bounds::{RefDataBounds, UNSIZED_BOUNDS}, - flag::RefDataFlag, + bounds::{RefBounds, UNSIZED_BOUNDS}, + flag::RefFlag, }; // Box:ref():ref() should not be able to modify, Only for external const BOX_REF_REF_FLAGS: u8 = 0; -const UNINIT_REF_FLAGS: u8 = RefDataFlag::Uninit.value(); +const UNINIT_REF_FLAGS: u8 = RefFlag::Uninit.value(); // | FfiRefFlag::Writable.value() // | FfiRefFlag::Readable.value() // | FfiRefFlag::Dereferenceable.value() @@ -33,11 +33,11 @@ const UNINIT_REF_FLAGS: u8 = RefDataFlag::Uninit.value(); pub struct RefData { ptr: ManuallyDrop>, pub flags: u8, - pub boundary: RefDataBounds, + pub boundary: RefBounds, } impl RefData { - pub fn new(ptr: *mut (), flags: u8, boundary: RefDataBounds) -> Self { + pub fn new(ptr: *mut (), flags: u8, boundary: RefBounds) -> Self { Self { ptr: ManuallyDrop::new(Box::new(ptr)), flags, @@ -63,7 +63,7 @@ impl RefData { let luaref = lua.create_userdata(RefData::new( ptr::from_ref(&target.ptr) as *mut (), BOX_REF_REF_FLAGS, - RefDataBounds { + RefBounds { below: 0, above: size_of::(), }, @@ -76,7 +76,7 @@ impl RefData { } pub unsafe fn deref(&self) -> LuaResult { - u8_test(self.flags, RefDataFlag::Dereferenceable.value()) + u8_test(self.flags, RefFlag::Dereferenceable.value()) .then_some(()) .ok_or_else(|| LuaError::external("This pointer is not dereferenceable."))?; @@ -104,7 +104,7 @@ impl RefData { } pub unsafe fn offset(&self, offset: isize) -> LuaResult { - u8_test(self.flags, RefDataFlag::Offsetable.value()) + u8_test(self.flags, RefFlag::Offsetable.value()) .then_some(()) .ok_or_else(|| LuaError::external("This pointer is not offsetable."))?; @@ -132,7 +132,7 @@ impl RefData { impl Drop for RefData { fn drop(&mut self) { - if u8_test_not(self.flags, RefDataFlag::Leaked.value()) { + if u8_test_not(self.flags, RefFlag::Leaked.value()) { unsafe { ManuallyDrop::drop(&mut self.ptr) }; } } @@ -146,10 +146,10 @@ impl FfiData for RefData { **self.ptr } fn is_readable(&self) -> bool { - u8_test(self.flags, RefDataFlag::Readable.value()) + u8_test(self.flags, RefFlag::Readable.value()) } fn is_writable(&self) -> bool { - u8_test(self.flags, RefDataFlag::Writable.value()) + u8_test(self.flags, RefFlag::Writable.value()) } } diff --git a/crates/lune-std-ffi/src/ffi/arg.rs b/crates/lune-std-ffi/src/ffi/arg.rs deleted file mode 100644 index 9d895fe..0000000 --- a/crates/lune-std-ffi/src/ffi/arg.rs +++ /dev/null @@ -1,16 +0,0 @@ -use super::FfiConvert; - -pub struct FfiArgRefOption { - pub flag: u8, -} - -pub enum FfiArgType { - FfiBox, - FfiRef(FfiArgRefOption), -} - -pub struct FfiArgInfo { - pub conv: *const dyn FfiConvert, - pub size: usize, - // pub kind: NativeArgType, -} diff --git a/crates/lune-std-ffi/src/ffi/libffi_helper.rs b/crates/lune-std-ffi/src/ffi/libffi_helper.rs index 2c0d1e0..fc93d04 100644 --- a/crates/lune-std-ffi/src/ffi/libffi_helper.rs +++ b/crates/lune-std-ffi/src/ffi/libffi_helper.rs @@ -26,7 +26,7 @@ pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult { unsafe { Ok((*ffi_type).size) } } -pub const SIEE_OF_POINTER: usize = size_of::<*mut ()>(); +pub const SIZE_OF_POINTER: usize = size_of::<*mut ()>(); // Converts ffi status into &str pub const FFI_STATUS_NAMES: [&str; 4] = [ diff --git a/crates/lune-std-ffi/src/ffi/mod.rs b/crates/lune-std-ffi/src/ffi/mod.rs index c1a6822..bebe31f 100644 --- a/crates/lune-std-ffi/src/ffi/mod.rs +++ b/crates/lune-std-ffi/src/ffi/mod.rs @@ -2,12 +2,12 @@ use std::cell::Ref; use mlua::prelude::*; -mod arg; pub mod association; pub mod bit_mask; mod cast; pub mod libffi_helper; -mod result; + +pub use self::cast::num_cast; pub trait FfiSize { fn get_size(&self) -> usize; @@ -46,4 +46,26 @@ pub trait FfiData { fn is_readable(&self) -> bool; } -pub use self::{arg::FfiArgInfo, cast::num_cast, result::FfiResultInfo}; +pub struct FfiArg { + pub size: usize, + pub callback_ref_flag: u8, +} + +impl Clone for FfiArg { + fn clone(&self) -> Self { + Self { + size: self.size, + callback_ref_flag: self.callback_ref_flag, + } + } +} + +pub struct FfiResult { + pub size: usize, +} + +impl Clone for FfiResult { + fn clone(&self) -> Self { + Self { size: self.size } + } +} diff --git a/crates/lune-std-ffi/src/ffi/result.rs b/crates/lune-std-ffi/src/ffi/result.rs deleted file mode 100644 index 06bd808..0000000 --- a/crates/lune-std-ffi/src/ffi/result.rs +++ /dev/null @@ -1,12 +0,0 @@ -use super::FfiConvert; - -// pub enum NativeResultType { -// FfiBox, -// FfiRef, -// } - -pub struct FfiResultInfo { - pub conv: *const dyn FfiConvert, - pub size: usize, - // kind: NativeResultType, -} diff --git a/crates/lune-std-ffi/src/lib.rs b/crates/lune-std-ffi/src/lib.rs index 18b9648..b008522 100644 --- a/crates/lune-std-ffi/src/lib.rs +++ b/crates/lune-std-ffi/src/lib.rs @@ -32,7 +32,7 @@ pub fn module(lua: &Lua) -> LuaResult { .with_function("uninitRef", |_lua, ()| Ok(RefData::new_uninit()))? .with_function("isInteger", |_lua, num: LuaValue| Ok(num.is_integer()))? .with_function("fnInfo", |lua, (args, ret): (LuaTable, LuaAnyUserData)| { - CFnInfo::new_from_table(lua, args, ret) + CFnInfo::from_table(lua, args, ret) })?; #[cfg(debug_assertions)]