From b31f81459f2e2270938520ebf8d41406137b0a35 Mon Sep 17 00:00:00 2001 From: qwreey Date: Mon, 21 Oct 2024 10:52:58 +0000 Subject: [PATCH] Move c ABI related object and functions into ffi.c (#243) --- crates/lune-std-ffi/src/c/arr_info.rs | 6 +- crates/lune-std-ffi/src/c/fn_info.rs | 18 ++- crates/lune-std-ffi/src/c/helper.rs | 25 ++-- crates/lune-std-ffi/src/c/mod.rs | 16 +++ crates/lune-std-ffi/src/c/ptr_info.rs | 15 +-- crates/lune-std-ffi/src/c/string_info.rs | 0 crates/lune-std-ffi/src/c/struct_info.rs | 11 +- crates/lune-std-ffi/src/c/type_info.rs | 4 +- crates/lune-std-ffi/src/c/types/f32.rs | 10 +- crates/lune-std-ffi/src/c/types/f64.rs | 10 +- crates/lune-std-ffi/src/c/types/i128.rs | 10 +- crates/lune-std-ffi/src/c/types/i16.rs | 10 +- crates/lune-std-ffi/src/c/types/i32.rs | 10 +- crates/lune-std-ffi/src/c/types/i64.rs | 10 +- crates/lune-std-ffi/src/c/types/i8.rs | 24 +++- crates/lune-std-ffi/src/c/types/isize.rs | 10 +- crates/lune-std-ffi/src/c/types/u128.rs | 10 +- crates/lune-std-ffi/src/c/types/u16.rs | 10 +- crates/lune-std-ffi/src/c/types/u32.rs | 10 +- crates/lune-std-ffi/src/c/types/u64.rs | 10 +- crates/lune-std-ffi/src/c/types/u8.rs | 10 +- crates/lune-std-ffi/src/c/types/usize.rs | 14 ++- crates/lune-std-ffi/src/c/void_info.rs | 2 + crates/lune-std-ffi/src/data/box_data/mod.rs | 6 +- crates/lune-std-ffi/src/data/callable_data.rs | 39 +++---- crates/lune-std-ffi/src/data/closure_data.rs | 21 +++- crates/lune-std-ffi/src/data/ref_data/mod.rs | 25 ++-- crates/lune-std-ffi/src/ffi/cast.rs | 4 +- crates/lune-std-ffi/src/ffi/mod.rs | 4 +- crates/lune-std-ffi/src/lib.rs | 17 +-- tests/ffi/external_closure/init.luau | 24 ++++ tests/ffi/external_closure/lib.c | 14 +++ tests/ffi/external_math/init.luau | 29 +++-- tests/ffi/external_pointer/init.luau | 23 ++++ tests/ffi/external_pointer/lib.c | 3 + tests/ffi/external_print/init.luau | 6 +- types/ffi.luau | 107 ++++++++++-------- 37 files changed, 345 insertions(+), 232 deletions(-) create mode 100644 crates/lune-std-ffi/src/c/string_info.rs create mode 100644 tests/ffi/external_closure/init.luau create mode 100644 tests/ffi/external_closure/lib.c create mode 100644 tests/ffi/external_pointer/init.luau create mode 100644 tests/ffi/external_pointer/lib.c diff --git a/crates/lune-std-ffi/src/c/arr_info.rs b/crates/lune-std-ffi/src/c/arr_info.rs index 59dce1a..4facbd2 100644 --- a/crates/lune-std-ffi/src/c/arr_info.rs +++ b/crates/lune-std-ffi/src/c/arr_info.rs @@ -140,9 +140,9 @@ impl FfiConvert for CArrInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - dst.get_pointer() + dst.get_inner_pointer() .byte_offset(dst_offset) - .copy_from(src.get_pointer().byte_offset(src_offset), self.get_size()); + .copy_from(src.get_inner_pointer().byte_offset(src_offset), self.get_size()); Ok(()) } } @@ -161,7 +161,7 @@ impl LuaUserData for CArrInfo { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Subtype - method_provider::provide_ptr_info(methods); + method_provider::provide_ptr(methods); // ToString method_provider::provide_to_string(methods); diff --git a/crates/lune-std-ffi/src/c/fn_info.rs b/crates/lune-std-ffi/src/c/fn_info.rs index 1fe4ec7..62df9e8 100644 --- a/crates/lune-std-ffi/src/c/fn_info.rs +++ b/crates/lune-std-ffi/src/c/fn_info.rs @@ -12,7 +12,10 @@ use super::{ }; use crate::{ data::{CallableData, ClosureData, RefData, RefFlag}, - ffi::{association, bit_mask::*, FfiArg, FfiData, FfiResult, FfiSignedness, FfiSize}, + ffi::{ + association, bit_mask::*, libffi_helper::SIZE_OF_POINTER, FfiArg, FfiData, FfiResult, + FfiSignedness, FfiSize, + }, }; // cfn is a type declaration for a function. @@ -42,9 +45,10 @@ impl FfiSignedness for CFnInfo { false } } + impl FfiSize for CFnInfo { fn get_size(&self) -> usize { - size_of::<*mut ()>() + SIZE_OF_POINTER } } @@ -186,7 +190,7 @@ impl CFnInfo { self.cif.as_raw_ptr(), self.arg_info_list.clone(), self.result_info.clone(), - ffi_ref.get_pointer(), + ffi_ref.get_inner_pointer(), ) })?; @@ -195,13 +199,17 @@ impl CFnInfo { Ok(callable) } + + pub fn get_middle_type() -> Type { + Type::void() + } } impl LuaUserData for CFnInfo { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Subtype - method_provider::provide_ptr_info(methods); - method_provider::provide_arr_info(methods); + method_provider::provide_ptr(methods); + method_provider::provide_arr(methods); // ToString method_provider::provide_to_string(methods); diff --git a/crates/lune-std-ffi/src/c/helper.rs b/crates/lune-std-ffi/src/c/helper.rs index 7f452fe..65e5dd2 100644 --- a/crates/lune-std-ffi/src/c/helper.rs +++ b/crates/lune-std-ffi/src/c/helper.rs @@ -10,6 +10,7 @@ use crate::{ pub mod method_provider { use super::*; + pub fn provide_to_string<'lua, Target, M>(methods: &mut M) where M: LuaUserDataMethods<'lua, Target>, @@ -19,20 +20,20 @@ pub mod method_provider { }); } - pub fn provide_ptr_info<'lua, Target, M>(methods: &mut M) + pub fn provide_ptr<'lua, Target, M>(methods: &mut M) where M: LuaUserDataMethods<'lua, Target>, { - methods.add_function("ptrInfo", |lua, this: LuaAnyUserData| { + methods.add_function("ptr", |lua, this: LuaAnyUserData| { CPtrInfo::from_userdata(lua, &this) }); } - pub fn provide_arr_info<'lua, Target, M>(methods: &mut M) + pub fn provide_arr<'lua, Target, M>(methods: &mut M) where M: LuaUserDataMethods<'lua, Target>, { - methods.add_function("ArrInfo", |lua, (this, length): (LuaAnyUserData, usize)| { + methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| { CArrInfo::from_userdata(lua, &this, length) }); } @@ -48,7 +49,7 @@ pub mod method_provider { let offset = offset.unwrap_or(0); let data_handle = &target.get_ffi_data()?; - if !data_handle.check_boundary(offset, this.get_size()) { + if !data_handle.check_inner_boundary(offset, this.get_size()) { return Err(LuaError::external("Out of bounds")); } if !data_handle.is_readable() { @@ -72,7 +73,7 @@ pub mod method_provider { let data_handle = &target.get_ffi_data()?; // use or functions - if !data_handle.check_boundary(offset, this.get_size()) { + if !data_handle.check_inner_boundary(offset, this.get_size()) { return Err(LuaError::external("Out of bounds")); } if !data_handle.is_writable() { @@ -104,7 +105,7 @@ pub mod method_provider { let dst = &dst.get_ffi_data()?; // use or functions - if !dst.check_boundary(dst_offset, this.get_size()) { + if !dst.check_inner_boundary(dst_offset, this.get_size()) { return Err(LuaError::external("Out of bounds")); } if !dst.is_writable() { @@ -112,7 +113,7 @@ pub mod method_provider { } let src = &src.get_ffi_data()?; - if !src.check_boundary(dst_offset, this.get_size()) { + if !src.check_inner_boundary(dst_offset, this.get_size()) { return Err(LuaError::external("Out of bounds")); } if !src.is_readable() { @@ -189,7 +190,7 @@ pub fn get_userdata(value: LuaValue) -> LuaResult { Ok(field_type) } else { Err(LuaError::external(format!( - "Unexpected field. CStruct, CType or CArr is required for element but got {}", + "CStruct, CType, CFn, CVoid or CArr is required but got {}", pretty_format_value(&value, &ValueFormatConfig::new()) ))) } @@ -242,6 +243,8 @@ pub fn get_size(userdata: &LuaAnyUserData) -> LuaResult { Ok(userdata.borrow::()?.get_size()) } else if userdata.is::() { Ok(userdata.borrow::()?.get_size()) + } else if userdata.is::() { + Ok(userdata.borrow::()?.get_size()) } else { ctype_helper::get_size(userdata) } @@ -259,9 +262,11 @@ pub fn get_middle_type(userdata: &LuaAnyUserData) -> LuaResult { Ok(CPtrInfo::get_middle_type()) } else if userdata.is::() { Ok(CVoidInfo::get_middle_type()) + } else if userdata.is::() { + Ok(CFnInfo::get_middle_type()) } else { Err(LuaError::external(format!( - "Unexpected field. CStruct, CType, CString or CArr is required for element but got {}", + "CStruct, CType, CFn, CVoid or CArr is required but got {}", pretty_format_value( // Since the data is in the Lua location, // there is no problem with the clone. diff --git a/crates/lune-std-ffi/src/c/mod.rs b/crates/lune-std-ffi/src/c/mod.rs index ffd4562..10b9e68 100644 --- a/crates/lune-std-ffi/src/c/mod.rs +++ b/crates/lune-std-ffi/src/c/mod.rs @@ -1,3 +1,6 @@ +use lune_utils::TableBuilder; +use mlua::prelude::*; + mod arr_info; mod fn_info; pub mod helper; @@ -30,3 +33,16 @@ mod association_names { pub const CLOSURE_FUNC: &str = "__closure_func"; pub const CLOSURE_CFN: &str = "__closure_cfn"; } + +pub fn export(lua: &Lua) -> LuaResult { + TableBuilder::new(lua)? + .with_value("void", CVoidInfo::new())? + .with_values(export_ctypes(lua)?)? + .with_function("struct", |lua, types: LuaTable| { + CStructInfo::from_table(lua, types) + })? + .with_function("fn", |lua, (args, ret): (LuaTable, LuaAnyUserData)| { + CFnInfo::from_table(lua, args, ret) + })? + .build_readonly() +} diff --git a/crates/lune-std-ffi/src/c/ptr_info.rs b/crates/lune-std-ffi/src/c/ptr_info.rs index 603c63f..f39b425 100644 --- a/crates/lune-std-ffi/src/c/ptr_info.rs +++ b/crates/lune-std-ffi/src/c/ptr_info.rs @@ -46,9 +46,9 @@ impl FfiConvert for CPtrInfo { .as_userdata() .ok_or_else(|| LuaError::external("CPtrInfo:writeRef only allows data"))?; *data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) - .cast::<*mut ()>() = value_userdata.get_ffi_data()?.get_pointer(); + .cast::<*mut ()>() = value_userdata.get_ffi_data()?.get_inner_pointer(); Ok(()) } @@ -60,7 +60,7 @@ impl FfiConvert for CPtrInfo { data_handle: &Ref, ) -> LuaResult> { Ok(LuaValue::UserData(lua.create_userdata(RefData::new( - unsafe { data_handle.get_pointer().byte_offset(offset) }, + unsafe { data_handle.get_inner_pointer().byte_offset(offset) }, if self.inner_is_cptr { READ_CPTR_REF_FLAGS } else { @@ -78,8 +78,9 @@ impl FfiConvert for CPtrInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::<*mut ()>() = - src.get_pointer().byte_offset(src_offset); + *dst.get_inner_pointer() + .byte_offset(dst_offset) + .cast::<*mut ()>() = src.get_inner_pointer().byte_offset(src_offset); Ok(()) } } @@ -133,8 +134,8 @@ impl LuaUserData for CPtrInfo { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Subtype - method_provider::provide_ptr_info(methods); - method_provider::provide_arr_info(methods); + method_provider::provide_ptr(methods); + method_provider::provide_arr(methods); // ToString method_provider::provide_to_string(methods); diff --git a/crates/lune-std-ffi/src/c/string_info.rs b/crates/lune-std-ffi/src/c/string_info.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/lune-std-ffi/src/c/struct_info.rs b/crates/lune-std-ffi/src/c/struct_info.rs index 1e52e36..3abbe73 100644 --- a/crates/lune-std-ffi/src/c/struct_info.rs +++ b/crates/lune-std-ffi/src/c/struct_info.rs @@ -172,9 +172,10 @@ impl FfiConvert for CStructInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - dst.get_pointer() - .byte_offset(dst_offset) - .copy_from(src.get_pointer().byte_offset(src_offset), self.get_size()); + dst.get_inner_pointer().byte_offset(dst_offset).copy_from( + src.get_inner_pointer().byte_offset(src_offset), + self.get_size(), + ); Ok(()) } } @@ -185,8 +186,8 @@ impl LuaUserData for CStructInfo { } fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Subtype - method_provider::provide_ptr_info(methods); - method_provider::provide_arr_info(methods); + method_provider::provide_ptr(methods); + method_provider::provide_arr(methods); // ToString method_provider::provide_to_string(methods); diff --git a/crates/lune-std-ffi/src/c/type_info.rs b/crates/lune-std-ffi/src/c/type_info.rs index 7e4b16d..38bc8db 100644 --- a/crates/lune-std-ffi/src/c/type_info.rs +++ b/crates/lune-std-ffi/src/c/type_info.rs @@ -98,8 +98,8 @@ where fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { // Subtype - method_provider::provide_ptr_info(methods); - method_provider::provide_arr_info(methods); + method_provider::provide_ptr(methods); + method_provider::provide_arr(methods); // ToString method_provider::provide_to_string(methods); diff --git a/crates/lune-std-ffi/src/c/types/f32.rs b/crates/lune-std-ffi/src/c/types/f32.rs index 00d06fb..10c1234 100644 --- a/crates/lune-std-ffi/src/c/types/f32.rs +++ b/crates/lune-std-ffi/src/c/types/f32.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/f64.rs b/crates/lune-std-ffi/src/c/types/f64.rs index fafa98d..ccbe431 100644 --- a/crates/lune-std-ffi/src/c/types/f64.rs +++ b/crates/lune-std-ffi/src/c/types/f64.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/i128.rs b/crates/lune-std-ffi/src/c/types/i128.rs index 6069e74..1ceeaaf 100644 --- a/crates/lune-std-ffi/src/c/types/i128.rs +++ b/crates/lune-std-ffi/src/c/types/i128.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/i16.rs b/crates/lune-std-ffi/src/c/types/i16.rs index a1c702a..2cc5ed8 100644 --- a/crates/lune-std-ffi/src/c/types/i16.rs +++ b/crates/lune-std-ffi/src/c/types/i16.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/i32.rs b/crates/lune-std-ffi/src/c/types/i32.rs index fa2b982..7cbfa81 100644 --- a/crates/lune-std-ffi/src/c/types/i32.rs +++ b/crates/lune-std-ffi/src/c/types/i32.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/i64.rs b/crates/lune-std-ffi/src/c/types/i64.rs index f458f9c..cc16c98 100644 --- a/crates/lune-std-ffi/src/c/types/i64.rs +++ b/crates/lune-std-ffi/src/c/types/i64.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/i8.rs b/crates/lune-std-ffi/src/c/types/i8.rs index 5f902cd..ea778e2 100644 --- a/crates/lune-std-ffi/src/c/types/i8.rs +++ b/crates/lune-std-ffi/src/c/types/i8.rs @@ -33,7 +33,10 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle + .get_inner_pointer() + .byte_offset(offset) + .cast::()) = value; } Ok(()) } @@ -44,8 +47,13 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult> { - let value = - unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; + let value = unsafe { + (*data_handle + .get_inner_pointer() + .byte_offset(offset) + .cast::()) + .into_lua(lua)? + }; Ok(value) } unsafe fn copy_data( @@ -56,8 +64,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -66,6 +74,10 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle + .get_inner_pointer() + .byte_offset(offset) + .cast::()) + .to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/isize.rs b/crates/lune-std-ffi/src/c/types/isize.rs index 6e1ef6c..3ded313 100644 --- a/crates/lune-std-ffi/src/c/types/isize.rs +++ b/crates/lune-std-ffi/src/c/types/isize.rs @@ -38,7 +38,7 @@ impl FfiConvert for CTypeInfo { }; unsafe { *(data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) = value; } @@ -53,7 +53,7 @@ impl FfiConvert for CTypeInfo { ) -> LuaResult> { let value = unsafe { (*data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) .into_lua(lua)? @@ -68,8 +68,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -79,7 +79,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult { Ok((*data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) .to_string()) diff --git a/crates/lune-std-ffi/src/c/types/u128.rs b/crates/lune-std-ffi/src/c/types/u128.rs index 12b0652..880bb05 100644 --- a/crates/lune-std-ffi/src/c/types/u128.rs +++ b/crates/lune-std-ffi/src/c/types/u128.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/u16.rs b/crates/lune-std-ffi/src/c/types/u16.rs index fd51298..9a367b3 100644 --- a/crates/lune-std-ffi/src/c/types/u16.rs +++ b/crates/lune-std-ffi/src/c/types/u16.rs @@ -38,7 +38,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -50,7 +50,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -62,8 +62,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -72,6 +72,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/u32.rs b/crates/lune-std-ffi/src/c/types/u32.rs index d28d310..59c7691 100644 --- a/crates/lune-std-ffi/src/c/types/u32.rs +++ b/crates/lune-std-ffi/src/c/types/u32.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/u64.rs b/crates/lune-std-ffi/src/c/types/u64.rs index 2ef7afc..ef08a10 100644 --- a/crates/lune-std-ffi/src/c/types/u64.rs +++ b/crates/lune-std-ffi/src/c/types/u64.rs @@ -37,7 +37,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -49,7 +49,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = unsafe { - (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? + (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } @@ -61,8 +61,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -71,6 +71,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/u8.rs b/crates/lune-std-ffi/src/c/types/u8.rs index ad6436f..b1e421e 100644 --- a/crates/lune-std-ffi/src/c/types/u8.rs +++ b/crates/lune-std-ffi/src/c/types/u8.rs @@ -34,7 +34,7 @@ impl FfiConvert for CTypeInfo { } }; unsafe { - *(data_handle.get_pointer().byte_offset(offset).cast::()) = value; + *(data_handle.get_inner_pointer().byte_offset(offset).cast::()) = value; } Ok(()) } @@ -48,7 +48,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult> { let value = - unsafe { (*data_handle.get_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; + unsafe { (*data_handle.get_inner_pointer().byte_offset(offset).cast::()).into_lua(lua)? }; Ok(value) } unsafe fn copy_data( @@ -59,8 +59,8 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer().byte_offset(dst_offset).cast::() = + *src.get_inner_pointer().byte_offset(src_offset).cast::(); Ok(()) } unsafe fn stringify_data( @@ -69,6 +69,6 @@ impl FfiConvert for CTypeInfo { offset: isize, data_handle: &Ref, ) -> LuaResult { - Ok((*data_handle.get_pointer().byte_offset(offset).cast::()).to_string()) + Ok((*data_handle.get_inner_pointer().byte_offset(offset).cast::()).to_string()) } } diff --git a/crates/lune-std-ffi/src/c/types/usize.rs b/crates/lune-std-ffi/src/c/types/usize.rs index 007c3ca..ab97d23 100644 --- a/crates/lune-std-ffi/src/c/types/usize.rs +++ b/crates/lune-std-ffi/src/c/types/usize.rs @@ -38,7 +38,7 @@ impl FfiConvert for CTypeInfo { }; unsafe { *(data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) = value; } @@ -53,7 +53,7 @@ impl FfiConvert for CTypeInfo { ) -> LuaResult> { let value = unsafe { (*data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) .into_lua(lua)? @@ -68,8 +68,12 @@ impl FfiConvert for CTypeInfo { dst: &Ref, src: &Ref, ) -> LuaResult<()> { - *dst.get_pointer().byte_offset(dst_offset).cast::() = - *src.get_pointer().byte_offset(src_offset).cast::(); + *dst.get_inner_pointer() + .byte_offset(dst_offset) + .cast::() = *src + .get_inner_pointer() + .byte_offset(src_offset) + .cast::(); Ok(()) } unsafe fn stringify_data( @@ -79,7 +83,7 @@ impl FfiConvert for CTypeInfo { data_handle: &Ref, ) -> LuaResult { Ok((*data_handle - .get_pointer() + .get_inner_pointer() .byte_offset(offset) .cast::()) .to_string()) diff --git a/crates/lune-std-ffi/src/c/void_info.rs b/crates/lune-std-ffi/src/c/void_info.rs index 0d36a35..5601ab0 100644 --- a/crates/lune-std-ffi/src/c/void_info.rs +++ b/crates/lune-std-ffi/src/c/void_info.rs @@ -3,6 +3,8 @@ use mlua::prelude::*; use crate::ffi::{FfiSignedness, FfiSize}; +use super::method_provider; + pub struct CVoidInfo(); impl FfiSignedness for CVoidInfo { 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 97ee9e1..1ca0770 100644 --- a/crates/lune-std-ffi/src/data/box_data/mod.rs +++ b/crates/lune-std-ffi/src/data/box_data/mod.rs @@ -74,7 +74,7 @@ impl BoxData { ) -> LuaResult> { let target = this.borrow::()?; let mut bounds = RefBounds::new(0, target.size()); - let mut ptr = unsafe { target.get_pointer() }; + let mut ptr = unsafe { target.get_inner_pointer() }; // Calculate offset if let Some(t) = offset { @@ -121,13 +121,13 @@ impl Drop for BoxData { } impl FfiData for BoxData { - fn check_boundary(&self, offset: isize, size: usize) -> bool { + fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { if offset < 0 { return false; } self.size() - (offset as usize) >= size } - unsafe fn get_pointer(&self) -> *mut () { + unsafe fn get_inner_pointer(&self) -> *mut () { self.data.as_ptr().cast_mut().cast::<()>() } fn is_readable(&self) -> bool { diff --git a/crates/lune-std-ffi/src/data/callable_data.rs b/crates/lune-std-ffi/src/data/callable_data.rs index 8a3f6ac..51673de 100644 --- a/crates/lune-std-ffi/src/data/callable_data.rs +++ b/crates/lune-std-ffi/src/data/callable_data.rs @@ -7,8 +7,8 @@ use libffi::{ }; use mlua::prelude::*; -use super::GetFfiData; -use crate::ffi::{FfiArg, FfiResult}; +use super::{GetFfiData, RefData}; +use crate::ffi::{FfiArg, FfiData, FfiResult}; pub struct CallableData { cif: *mut ffi_cif, @@ -42,33 +42,24 @@ impl CallableData { ptr::null_mut() } else { let result_data = result.get_ffi_data()?; - if result_data.check_boundary(0, self.result_info.size) { + if !result_data.check_inner_boundary(0, self.result_info.size) { return Err(LuaError::external("Result boundary check failed")); } - result_data.get_pointer() + result_data.get_inner_pointer() } .cast::(); for index in 0..self.arg_info_list.len() { - let arg_info = self.arg_info_list.get(index).unwrap(); - let arg = args + // let arg_info = self.arg_info_list.get(index).unwrap(); + let arg_value = args .get(index) - .ok_or_else(|| LuaError::external(format!("argument {index} required")))?; + .ok_or_else(|| LuaError::external(format!("argument {index} required")))? + .as_userdata() + .ok_or_else(|| LuaError::external("argument should be Ref"))?; - let arg_pointer = if let LuaValue::UserData(userdata) = arg { - // BoxData, RefData, ... - let data_handle = userdata.get_ffi_data()?; - if !data_handle.check_boundary(0, arg_info.size) { - return Err(LuaError::external(format!( - "argument {index} boundary check failed" - ))); - } - data_handle.get_pointer() - } else { - // FIXME: buffer, string here - return Err(LuaError::external("unimpl")); - }; - arg_list.push(arg_pointer.cast::()); + let arg_ref = arg_value.borrow::()?; + + arg_list.push(arg_ref.get_inner_pointer().cast::()); } ffi_call( @@ -84,16 +75,14 @@ impl CallableData { impl LuaUserData for CallableData { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_method( - "call", + methods.add_meta_method( + LuaMetaMethod::Call, |_lua, this: &CallableData, mut args: LuaMultiValue| { let result = args.pop_front().ok_or_else(|| { LuaError::external("First argument must be result data handle or nil") })?; - // FIXME: clone unsafe { this.call(result, args) } }, ); - // ref, leak ..? } } diff --git a/crates/lune-std-ffi/src/data/closure_data.rs b/crates/lune-std-ffi/src/data/closure_data.rs index e05e961..7f49878 100644 --- a/crates/lune-std-ffi/src/data/closure_data.rs +++ b/crates/lune-std-ffi/src/data/closure_data.rs @@ -39,11 +39,14 @@ unsafe extern "C" fn callback( arg_pointers: *mut *mut c_void, closure_data: *mut c_void, ) { + dbg!("before ud"); 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); + dbg!("before result"); + // Push result pointer (ref) args.push(LuaValue::UserData( lua.create_userdata(RefData::new( @@ -54,6 +57,8 @@ unsafe extern "C" fn callback( .unwrap(), )); + dbg!("before arg"); + // Push arg pointer (ref) for i in 0..len { let arg_info = closure_data.arg_info_list.get(i).unwrap(); @@ -67,6 +72,8 @@ unsafe extern "C" fn callback( )); } + dbg!("before call"); + closure_data .func .borrow() @@ -112,10 +119,12 @@ impl ClosureData { } impl FfiData for ClosureData { - unsafe fn get_pointer(&self) -> *mut () { - self.code.as_mut_ptr().cast::<()>() + unsafe fn get_inner_pointer(&self) -> *mut () { + ptr::from_ref(&self.code.as_mut_ptr()) + .cast_mut() + .cast::<()>() } - fn check_boundary(&self, offset: isize, size: usize) -> bool { + fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { (offset as usize) + size <= SIZE_OF_POINTER } fn is_readable(&self) -> bool { @@ -126,4 +135,8 @@ impl FfiData for ClosureData { } } -impl LuaUserData for ClosureData {} +impl LuaUserData for ClosureData { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + // methods.add_function("ref", function); + } +} 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 b9a4cb6..b22b840 100644 --- a/crates/lune-std-ffi/src/data/ref_data/mod.rs +++ b/crates/lune-std-ffi/src/data/ref_data/mod.rs @@ -61,7 +61,7 @@ impl RefData { let target = this.borrow::()?; let luaref = lua.create_userdata(RefData::new( - ptr::from_ref(&target.ptr) as *mut (), + ptr::from_ref(&**target.ptr) as *mut (), BOX_REF_REF_FLAGS, RefBounds { below: 0, @@ -76,18 +76,15 @@ impl RefData { } pub unsafe fn deref(&self) -> LuaResult { - u8_test(self.flags, RefFlag::Dereferenceable.value()) - .then_some(()) - .ok_or_else(|| LuaError::external("This pointer is not dereferenceable."))?; + if !u8_test(self.flags, RefFlag::Dereferenceable.value()) { + return Err(LuaError::external("This pointer is not dereferenceable.")); + } - self.boundary - .check_sized(0, size_of::()) - .then_some(()) - .ok_or_else(|| { - LuaError::external( - "Offset is out of bounds. Dereferencing pointer requires size of usize", - ) - })?; + if !self.boundary.check_sized(0, size_of::()) { + return Err(LuaError::external( + "Offset is out of bounds. Dereferencing pointer requires size of usize", + )); + } // FIXME flags Ok(Self::new( @@ -139,10 +136,10 @@ impl Drop for RefData { } impl FfiData for RefData { - fn check_boundary(&self, offset: isize, size: usize) -> bool { + fn check_inner_boundary(&self, offset: isize, size: usize) -> bool { self.boundary.check_sized(offset, size) } - unsafe fn get_pointer(&self) -> *mut () { + unsafe fn get_inner_pointer(&self) -> *mut () { **self.ptr } fn is_readable(&self) -> bool { diff --git a/crates/lune-std-ffi/src/ffi/cast.rs b/crates/lune-std-ffi/src/ffi/cast.rs index 76fd18e..f0dc7ba 100644 --- a/crates/lune-std-ffi/src/ffi/cast.rs +++ b/crates/lune-std-ffi/src/ffi/cast.rs @@ -11,8 +11,8 @@ where From: AsPrimitive, Into: 'static + Copy, { - let from_ptr = unsafe { from.get_pointer().cast::() }; - let into_ptr = unsafe { into.get_pointer().cast::() }; + let from_ptr = unsafe { from.get_inner_pointer().cast::() }; + let into_ptr = unsafe { into.get_inner_pointer().cast::() }; unsafe { *into_ptr = (*from_ptr).as_(); diff --git a/crates/lune-std-ffi/src/ffi/mod.rs b/crates/lune-std-ffi/src/ffi/mod.rs index 5144bbd..66a11da 100644 --- a/crates/lune-std-ffi/src/ffi/mod.rs +++ b/crates/lune-std-ffi/src/ffi/mod.rs @@ -58,8 +58,8 @@ pub trait FfiConvert { } pub trait FfiData { - fn check_boundary(&self, offset: isize, size: usize) -> bool; - unsafe fn get_pointer(&self) -> *mut (); + fn check_inner_boundary(&self, offset: isize, size: usize) -> bool; + unsafe fn get_inner_pointer(&self) -> *mut (); fn is_writable(&self) -> bool; fn is_readable(&self) -> bool; } diff --git a/crates/lune-std-ffi/src/lib.rs b/crates/lune-std-ffi/src/lib.rs index 917602f..6fe320e 100644 --- a/crates/lune-std-ffi/src/lib.rs +++ b/crates/lune-std-ffi/src/lib.rs @@ -1,7 +1,5 @@ #![allow(clippy::cargo_common_metadata)] -use c::CVoidInfo; -use data::RefData; use lune_utils::TableBuilder; use mlua::prelude::*; @@ -10,8 +8,8 @@ mod data; mod ffi; use crate::{ - c::{export_ctypes, CFnInfo, CStructInfo}, - data::{create_nullptr, BoxData, LibData}, + c::export as c_export, + data::{create_nullptr, BoxData, LibData, RefData}, }; /** @@ -23,22 +21,15 @@ use crate::{ */ pub fn module(lua: &Lua) -> LuaResult { let result = TableBuilder::new(lua)? - .with_values(export_ctypes(lua)?)? - .with_value("void", CVoidInfo::new())? .with_function("nullRef", |lua, ()| create_nullptr(lua))? .with_function("box", |_lua, size: usize| Ok(BoxData::new(size)))? .with_function("open", |_lua, name: String| LibData::new(name))? - .with_function("structInfo", |lua, types: LuaTable| { - CStructInfo::from_table(lua, types) - })? .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::from_table(lua, args, ret) - })?; + .with_value("c", c_export(lua)?)?; #[cfg(debug_assertions)] - let result = result.with_function("debug_associate", |lua, str: String| { + let result = result.with_function("debugAssociation", |lua, str: String| { println!("WARNING: ffi.debug_associate is GC debug function, which only works for debug build. Do not use this function in production level codes."); ffi::association::get_table(lua, str.as_ref()) })?; diff --git a/tests/ffi/external_closure/init.luau b/tests/ffi/external_closure/init.luau new file mode 100644 index 0000000..55b38e6 --- /dev/null +++ b/tests/ffi/external_closure/init.luau @@ -0,0 +1,24 @@ +local ffi = require("@lune/ffi") + +local testdir = "./tests/ffi/external_closure" + +local compile = require("../utility/compile") +compile(`{testdir}/lib.c`, `{testdir}/lib.so`) + +local lib = ffi.open(`{testdir}/lib.so`) + +local function test_closure() + local callback_info = ffi.c.fn({ ffi.c.int, ffi.c.int }, ffi.c.int) + local callback_closure = callback_info:closure(function(ret, a, b) + ffi.c.int:writeData(ret, ffi.c.int:readData(a) + ffi.c.int:readData(b)) + end) + + local closure_test_info = ffi.c.fn({ callback_info }, ffi.c.int) + + local closure_test_callable = closure_test_info:callable(lib:find("closure_test")) + + local result_box = ffi.box(ffi.c.int.size) + closure_test_callable(result_box, callback_closure:ref()) +end + +test_closure() diff --git a/tests/ffi/external_closure/lib.c b/tests/ffi/external_closure/lib.c new file mode 100644 index 0000000..e4579f4 --- /dev/null +++ b/tests/ffi/external_closure/lib.c @@ -0,0 +1,14 @@ +#include + +typedef int (*lua_callback_t)(int a, int b); + +int closure_test(lua_callback_t callback) { + printf("%p\n", callback); + printf("%d\n", (*callback)(12, 24)); + + return (*callback)(12, 24) * 2; +} + +int closure(int a, int b) { + return a+b; +} diff --git a/tests/ffi/external_math/init.luau b/tests/ffi/external_math/init.luau index 0d00541..fe486b9 100644 --- a/tests/ffi/external_math/init.luau +++ b/tests/ffi/external_math/init.luau @@ -1,23 +1,22 @@ local ffi = require("@lune/ffi") +local c = ffi.c local testdir = "./tests/ffi/external_math" - local compile = require("../utility/compile") compile(`{testdir}/lib.c`, `{testdir}/lib.so`) - local lib = ffi.open(`{testdir}/lib.so`) local function test_add_int() - local add_int = ffi.fnInfo({ ffi.int, ffi.int }, ffi.int) + local add_int_info = c.fn({ c.int, c.int }, c.int) - local add_int_caller = add_int:callable(lib:find("add_int")) + local add_int_callable = add_int_info:callable(lib:find("add_int")) - local resultBox = ffi.box(ffi.int.size) - local arg1 = ffi.int:box(100) - local arg2 = ffi.int:box(200) + local result_box = ffi.box(c.int.size) + local arg1 = c.int:box(100) + local arg2 = c.int:box(200) - add_int_caller:call(resultBox, arg1, arg2) - local result = ffi.int:readData(resultBox) + add_int_callable(result_box, arg1:ref(), arg2:ref()) + local result = c.int:readData(result_box) assert(result == 300, `add_int failed. result expected 300, got {result}`) end @@ -25,16 +24,16 @@ end test_add_int() local function test_mul_int() - local mul_int = ffi.fnInfo({ ffi.int, ffi.int }, ffi.int) + local mul_int = c.fn({ c.int, c.int }, c.int) local mul_int_caller = mul_int:callable(lib:find("mul_int")) - local resultBox = ffi.box(ffi.int.size) - local arg1 = ffi.int:box(100) - local arg2 = ffi.int:box(200) + local resultBox = ffi.box(c.int.size) + local arg1 = c.int:box(100) + local arg2 = c.int:box(200) - mul_int_caller:call(resultBox, arg1, arg2) - local result = ffi.int:readData(resultBox) + mul_int_caller(resultBox, arg1:ref(), arg2:ref()) + local result = c.int:readData(resultBox) assert(result == 20000, `mul_int failed. result expected 20000, got {result}`) end diff --git a/tests/ffi/external_pointer/init.luau b/tests/ffi/external_pointer/init.luau new file mode 100644 index 0000000..22ab217 --- /dev/null +++ b/tests/ffi/external_pointer/init.luau @@ -0,0 +1,23 @@ +local ffi = require("@lune/ffi") +local c = ffi.c + +local testdir = "./tests/ffi/external_pointer" +local compile = require("../utility/compile") +compile(`{testdir}/lib.c`, `{testdir}/lib.so`) +local lib = ffi.open(`{testdir}/lib.so`) + +local function test_pointer() + local pointer_info = c.fn({ c.int:ptr() }, c.void) + + local pointer_callable = pointer_info:callable(lib:find("pointer")) + + local a = ffi.box(c.int.size) + + pointer_callable(nil, a:ref():ref()) + + local result = c.int:readData(a) + + assert(result == 123, `pointer failed. result expected 123, got {result}`) +end + +test_pointer() diff --git a/tests/ffi/external_pointer/lib.c b/tests/ffi/external_pointer/lib.c new file mode 100644 index 0000000..0714622 --- /dev/null +++ b/tests/ffi/external_pointer/lib.c @@ -0,0 +1,3 @@ +void pointer(int *a) { + *a = 123; +} diff --git a/tests/ffi/external_print/init.luau b/tests/ffi/external_print/init.luau index 4dad523..43ac11d 100644 --- a/tests/ffi/external_print/init.luau +++ b/tests/ffi/external_print/init.luau @@ -8,11 +8,11 @@ compile(`{testdir}/lib.c`, `{testdir}/lib.so`) local lib = ffi.open(`{testdir}/lib.so`) local function test_hello_world() - local add_int = ffi.fnInfo({}, ffi.void) + local hello_world_info = ffi.fnInfo({}, ffi.void) - local hello_world_caller = add_int:callable(lib:find("hello_world")) + local hello_world_callable = hello_world_info:callable(lib:find("hello_world")) - hello_world_caller:call(nil) + hello_world_callable:call(nil) end test_hello_world() diff --git a/types/ffi.luau b/types/ffi.luau index 2a7d767..b6af6dd 100644 --- a/types/ffi.luau +++ b/types/ffi.luau @@ -4,8 +4,8 @@ export type CTypeInfo = { signedness: boolean, -- subtype - ptrInfo: (self: CTypeInfo) -> CPtrInfo>, - arrInfo: (self: CTypeInfo, len: number) -> CArrInfo, R>, + ptr: (self: CTypeInfo) -> CPtrInfo>, + arr: (self: CTypeInfo, len: number) -> CArrInfo, R>, -- realize box: (self: CTypeInfo, val: R) -> Box, @@ -23,8 +23,8 @@ export type CPtrInfo = { -- subtype -- FIXME: recursive types; 'any' should be CPtrInfo - arrInfo: (self: CPtrInfo, len: number) -> any, - ptrInfo: (self: CPtrInfo) -> any, + arr: (self: CPtrInfo, len: number) -> any, + ptr: (self: CPtrInfo) -> any, readRef: (self: CPtrInfo, target: (Ref|Box), offset: number?) -> Ref, writeRef: (self: CPtrInfo, target: (Ref|Box), value: (Ref|Box), offset: number?) -> (), @@ -36,7 +36,7 @@ export type CArrInfo = { inner: T, -- subtype - ptrInfo: (self: CArrInfo) -> CPtrInfo, + ptr: (self: CArrInfo) -> CPtrInfo, -- realize box: (self: CArrInfo, table: { T }) -> Box, @@ -49,12 +49,12 @@ export type CArrInfo = { export type CFnInfo = { callable: (self: CFnInfo, functionRef: Ref) -> Callable, - closure: (self: CFnInfo, (...Ref)->()) -> (), + closure: (self: CFnInfo, (ret: Ref, ...Ref)->()) -> Closure, } export type CStructInfo = { - arrInfo: (self: CStructInfo, len: number) -> CArrInfo, - ptrInfo: (self: CStructInfo) -> CPtrInfo, + arr: (self: CStructInfo, len: number) -> CArrInfo, + ptr: (self: CStructInfo) -> CPtrInfo, box: (self: CStructInfo, table: { any }) -> Box, readData: (self: CStructInfo, target: (Ref|Box), offset: number?) -> { any }, @@ -62,7 +62,7 @@ export type CStructInfo = { } export type CVoidInfo = { - ptrInfo: (self: CVoidInfo) -> CPtrInfo, + ptr: (self: CVoidInfo) -> CPtrInfo, } type NumCType = CTypeInfo @@ -151,42 +151,60 @@ export type Lib = { find: (self: Lib, sym: string) -> Ref, } -export type Callable = { - call: (self: Callable, result: (Ref | Box)?, ...(Ref | Box))->(); +-- export type AppliedCallable = ()->() + +export type Callable = (ret: (Ref|Box)?, ...Ref)->() & { + -- apply: (self: Callable, args: Args)->AppliedCallable, } +export type Closure = { + ref: (self: Closure)->Ref, +} + +local c = {} + +c.u8 = {} :: u8 +c.u16 = {} :: u16 +c.u32 = {} :: u32 +c.u64 = {} :: u64 +c.u128 = {} :: u128 +c.i8 = {} :: i8 +c.i16 = {} :: i16 +c.i32 = {} :: i32 +c.i64 = {} :: i64 +c.i128 = {} :: i128 +c.f32 = {} :: f32 +c.f64 = {} :: f64 +c.usize = {} :: usize +c.isize = {} :: isize + +c.char = {} :: char +c.float = {} :: float +c.double = {} :: double +c.uchar = {} :: uchar +c.schar = {} :: schar +c.short = {} :: short +c.ushort = {} :: ushort +c.int = {} :: int +c.uint = {} :: uint +c.long = {} :: long +c.ulong = {} :: ulong +c.longlong = {} :: longlong +c.ulonglong = {} :: ulonglong + +c.void = {} :: CVoidInfo + +function c.fn(args: { CTypes }, ret: CTypes): CFnInfo + return nil :: any +end + +function c.struct(inner: { CTypes }): CStructInfo + return nil :: any +end + local ffi = {} -ffi.u8 = {} :: u8 -ffi.u16 = {} :: u16 -ffi.u32 = {} :: u32 -ffi.u64 = {} :: u64 -ffi.u128 = {} :: u128 -ffi.i8 = {} :: i8 -ffi.i16 = {} :: i16 -ffi.i32 = {} :: i32 -ffi.i64 = {} :: i64 -ffi.i128 = {} :: i128 -ffi.f32 = {} :: f32 -ffi.f64 = {} :: f64 -ffi.usize = {} :: usize -ffi.isize = {} :: isize - -ffi.char = {} :: char -ffi.float = {} :: float -ffi.double = {} :: double -ffi.uchar = {} :: uchar -ffi.schar = {} :: schar -ffi.short = {} :: short -ffi.ushort = {} :: ushort -ffi.int = {} :: int -ffi.uint = {} :: uint -ffi.long = {} :: long -ffi.ulong = {} :: ulong -ffi.longlong = {} :: longlong -ffi.ulonglong = {} :: ulonglong - -ffi.void = {} :: CVoidInfo +ffi.c = c function ffi.nullRef(): Ref return nil :: any @@ -208,12 +226,5 @@ function ffi.isInteger(val: T): boolean return nil :: any end -function ffi.fnInfo(args: { CTypes }, ret: CTypes): CFnInfo - return nil :: any -end - -function ffi.structInfo(inner: { CTypes }): CStructInfo - return nil :: any -end return ffi