From d60a1b99f65b0b05a6b5a331cff7386d02ea3479 Mon Sep 17 00:00:00 2001 From: qwreey Date: Sun, 25 Aug 2024 19:22:46 +0000 Subject: [PATCH] Use CType instead of CType (#243) --- crates/lune-std-ffi/src/c/c_arr.rs | 14 ++- crates/lune-std-ffi/src/c/c_helper.rs | 18 +-- crates/lune-std-ffi/src/c/c_struct.rs | 29 ++--- crates/lune-std-ffi/src/c/c_type.rs | 86 +++++++------- crates/lune-std-ffi/src/c/mod.rs | 133 +--------------------- crates/lune-std-ffi/src/c/types/c_int.rs | 38 +++++++ crates/lune-std-ffi/src/c/types/mod.rs | 8 ++ crates/lune-std-ffi/src/ffi/ffi_helper.rs | 2 +- crates/lune-std-ffi/src/ffi/ffi_ref.rs | 2 + 9 files changed, 128 insertions(+), 202 deletions(-) create mode 100644 crates/lune-std-ffi/src/c/types/c_int.rs create mode 100644 crates/lune-std-ffi/src/c/types/mod.rs diff --git a/crates/lune-std-ffi/src/c/c_arr.rs b/crates/lune-std-ffi/src/c/c_arr.rs index 2b2b94b..2a42019 100644 --- a/crates/lune-std-ffi/src/c/c_arr.rs +++ b/crates/lune-std-ffi/src/c/c_arr.rs @@ -1,3 +1,5 @@ +use std::any::Any; + use libffi::middle::Type; use mlua::prelude::*; @@ -54,13 +56,13 @@ impl CArr { Ok(carr) } - pub fn get_type(&self) -> Type { - self.struct_type.clone() + pub fn get_type(&self) -> &Type { + &self.struct_type } - // pub fn get_element_type(&self) -> Type { - // self.element_type.clone() - // } + pub fn get_element_type(&self) -> &Type { + &self.element_type + } // Stringify cstruct for pretty printing something like: // @@ -73,7 +75,7 @@ impl CArr { .as_userdata() .ok_or(LuaError::external("failed to get inner type userdata."))?; - if inner.is::() { + if inner.is::>() { Ok(format!( " {} ; {} ", stringify_userdata(inner)?, diff --git a/crates/lune-std-ffi/src/c/c_helper.rs b/crates/lune-std-ffi/src/c/c_helper.rs index d25843c..2a18096 100644 --- a/crates/lune-std-ffi/src/c/c_helper.rs +++ b/crates/lune-std-ffi/src/c/c_helper.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::ptr::{self, null_mut}; use libffi::{low, middle::Type, raw}; @@ -37,11 +38,11 @@ pub fn type_list_from_table(table: &LuaTable) -> LuaResult> { // get libffi_type from any c-type userdata pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult { if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) - } else if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) + Ok(userdata.borrow::()?.get_type().to_owned()) + } else if userdata.is::>() { + Ok(userdata.borrow::>()?.get_type().to_owned()) } else if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) + Ok(userdata.borrow::()?.get_type().to_owned()) } else if userdata.is::() { Ok(CPtr::get_type()) } else { @@ -59,9 +60,10 @@ pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult { // stringify any c-type userdata (for recursive) pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult { - if userdata.is::() { - let name = userdata.borrow::()?.stringify(); - Ok(name) + if userdata.is::>() { + Ok(String::from( + userdata.borrow::>()?.stringify(), + )) } else if userdata.is::() { let name = CStruct::stringify(userdata)?; Ok(name) @@ -80,7 +82,7 @@ pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult { pub fn name_from_userdata(userdata: &LuaAnyUserData) -> String { if userdata.is::() { String::from("CStruct") - } else if userdata.is::() { + } else if userdata.is::>() { String::from("CType") } else if userdata.is::() { String::from("CArr") diff --git a/crates/lune-std-ffi/src/c/c_struct.rs b/crates/lune-std-ffi/src/c/c_struct.rs index 58628d5..8812eb5 100644 --- a/crates/lune-std-ffi/src/c/c_struct.rs +++ b/crates/lune-std-ffi/src/c/c_struct.rs @@ -1,12 +1,9 @@ #![allow(clippy::cargo_common_metadata)] -use std::{borrow::Borrow, vec::Vec}; +use std::any::Any; +use std::vec::Vec; -use libffi::{ - low, - middle::{Cif, Type}, - raw, -}; +use libffi::{low, middle::Type, raw}; use mlua::prelude::*; use super::association_names::CSTRUCT_INNER; @@ -20,14 +17,14 @@ use crate::ffi::ffi_helper::FFI_STATUS_NAMES; pub struct CStruct { // libffi_cif: Cif, fields: Vec, - libffi_type: Type, + struct_type: Type, offsets: Vec, size: usize, } impl CStruct { pub fn new(fields: Vec) -> LuaResult { - let libffi_type = Type::structure(fields.iter().cloned()); + let struct_type = Type::structure(fields.iter().cloned()); // let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void()); // Get field offsets with ffi_get_struct_offsets @@ -35,7 +32,7 @@ impl CStruct { unsafe { let offset_result: raw::ffi_status = raw::ffi_get_struct_offsets( low::ffi_abi_FFI_DEFAULT_ABI, - libffi_type.as_raw_ptr(), + struct_type.as_raw_ptr(), offsets.as_mut_ptr(), ); if offset_result != raw::ffi_status_FFI_OK { @@ -49,12 +46,12 @@ impl CStruct { // Get tailing padded size of struct // See http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html - let size = unsafe { (*libffi_type.as_raw_ptr()).size }; + let size = unsafe { (*struct_type.as_raw_ptr()).size }; Ok(Self { // libffi_cif: libffi_cfi, fields, - libffi_type, + struct_type, offsets, size, }) @@ -85,7 +82,7 @@ impl CStruct { let mut result = String::from(" "); for i in 0..table.raw_len() { let child: LuaAnyUserData = table.raw_get(i + 1)?; - if child.is::() { + if child.is::>() { result.push_str(format!("{}, ", stringify_userdata(&child)?).as_str()); } else { result.push_str( @@ -117,8 +114,12 @@ impl CStruct { Ok(offset) } - pub fn get_type(&self) -> Type { - self.libffi_type.clone() + pub fn get_fields(&self) -> &Vec { + &self.fields + } + + pub fn get_type(&self) -> &Type { + &self.struct_type } } diff --git a/crates/lune-std-ffi/src/c/c_type.rs b/crates/lune-std-ffi/src/c/c_type.rs index 7ed7bca..3e4ee42 100644 --- a/crates/lune-std-ffi/src/c/c_type.rs +++ b/crates/lune-std-ffi/src/c/c_type.rs @@ -1,5 +1,7 @@ #![allow(clippy::cargo_common_metadata)] +use std::marker::PhantomData; + use libffi::middle::Type; use mlua::prelude::*; @@ -8,27 +10,20 @@ use super::c_helper::get_ensured_size; use super::c_ptr::CPtr; use crate::ffi::ffi_helper::get_ptr_from_userdata; -pub struct CType { +pub struct CType { // for ffi_ptrarray_to_raw? // libffi_cif: Cif, libffi_type: Type, size: usize, - name: Option, - - // Write converted data from luavalue into some ptr - pub luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>, - - // Read luavalue from some ptr - pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult, + name: Option<&'static str>, + _phantom: PhantomData, } -impl CType { - pub fn new( - libffi_type: Type, - name: Option, - luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>, - ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult, - ) -> LuaResult { +impl CType +where + T: ?Sized, +{ + pub fn new_with_libffi_type(libffi_type: Type, name: Option<&'static str>) -> LuaResult { // let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void()); let size = get_ensured_size(libffi_type.as_raw_ptr())?; Ok(Self { @@ -36,78 +31,83 @@ impl CType { libffi_type, size, name, - luavalue_into_ptr, - ptr_into_luavalue, + _phantom: PhantomData {}, }) } - pub fn get_type(&self) -> Type { - self.libffi_type.clone() + pub fn get_type(&self) -> &Type { + &self.libffi_type } - pub fn stringify(&self) -> String { - match &self.name { - Some(t) => t.to_owned(), - None => String::from("unnamed"), + pub fn stringify(&self) -> &str { + match self.name { + Some(t) => t, + None => "unnamed", } } +} - // Read data from ptr and convert it into luavalue - pub unsafe fn read_ptr<'lua>( +pub trait PtrHandle { + // Convert luavalue into data, then write into ptr + fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()>; + + // Read data from ptr, then convert into luavalue + fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult; + + // Read data from userdata (such as box or ref) and convert it into luavalue + unsafe fn read_userdata<'lua>( &self, lua: &'lua Lua, userdata: LuaAnyUserData<'lua>, offset: Option, ) -> LuaResult> { let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? }; - let value = (self.ptr_into_luavalue)(lua, ptr)?; + let value = Self::ptr_into_luavalue(lua, ptr)?; Ok(value) } - // Write converted data from luavalue into ptr - pub unsafe fn write_ptr<'lua>( + // Write data into userdata (such as box or ref) from luavalue + unsafe fn write_userdata<'lua>( &self, luavalue: LuaValue<'lua>, userdata: LuaAnyUserData<'lua>, offset: Option, ) -> LuaResult<()> { let ptr = unsafe { get_ptr_from_userdata(&userdata, offset)? }; - (self.luavalue_into_ptr)(luavalue, ptr)?; + Self::luavalue_into_ptr(luavalue, ptr)?; Ok(()) } } -impl LuaUserData for CType { +impl LuaUserData for CType +where + Self: Sized + PtrHandle, +{ fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fields.add_field_method_get("size", |_, this| Ok(this.size)); } fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_function("ptr", |lua, this: LuaAnyUserData| { - let pointer = CPtr::from_lua_userdata(lua, &this)?; - Ok(pointer) + CPtr::from_lua_userdata(lua, &this) }); methods.add_method( "from", - |lua, ctype, (userdata, offset): (LuaAnyUserData, Option)| { - let value = unsafe { ctype.read_ptr(lua, userdata, offset)? }; - Ok(value) + |lua, ctype, (userdata, offset): (LuaAnyUserData, Option)| unsafe { + ctype.read_userdata(lua, userdata, offset) }, ); methods.add_method( "into", - |_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option)| { - unsafe { ctype.write_ptr(value, userdata, offset)? }; - Ok(()) + |_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option)| unsafe { + ctype.write_userdata(value, userdata, offset) }, ); methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| { - let carr = CArr::from_lua_userdata(lua, &this, length)?; - Ok(carr) + CArr::from_lua_userdata(lua, &this, length) }); - methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| { - let name = this.stringify(); - Ok(name) + methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| { + lua.create_string(this.stringify()) }); } } diff --git a/crates/lune-std-ffi/src/c/mod.rs b/crates/lune-std-ffi/src/c/mod.rs index 25db176..be3364d 100644 --- a/crates/lune-std-ffi/src/c/mod.rs +++ b/crates/lune-std-ffi/src/c/mod.rs @@ -5,6 +5,9 @@ pub(super) mod c_ptr; pub(super) mod c_string; pub(super) mod c_struct; pub(super) mod c_type; +pub(super) mod types; + +pub use types::create_all_types; // Named registry table names mod association_names { @@ -12,133 +15,3 @@ mod association_names { pub const CARR_INNER: &str = "__carr_inner"; pub const CSTRUCT_INNER: &str = "__cstruct_inner"; } - -use core::ffi::{ - c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, - c_ulong, c_ulonglong, c_ushort, c_void, -}; - -use libffi::middle::Type; -use mlua::prelude::*; - -use self::c_type::CType; -use crate::ffi::ffi_platform::CHAR_IS_SIGNED; - -// export all default c-types -#[allow(clippy::too_many_lines)] -pub fn create_all_types(lua: &Lua) -> LuaResult> { - Ok(vec![ - ( - "int", - CType::new( - Type::c_int(), - Some(String::from("int")), - |data, ptr| { - let value = match data { - LuaValue::Integer(t) => t, - _ => { - return Err(LuaError::external(format!( - "Integer expected, got {}", - data.type_name() - ))) - } - } as c_int; - unsafe { - *(ptr.cast::()) = value; - } - Ok(()) - }, - |lua: &Lua, ptr: *mut ()| { - let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; - Ok(value) - }, - )? - .into_lua(lua)?, - ), - ( - "long", - CType::new( - Type::c_long(), - Some(String::from("long")), - |data, ptr| { - let value = match data { - LuaValue::Integer(t) => t, - _ => { - return Err(LuaError::external(format!( - "Integer expected, got {}", - data.type_name() - ))) - } - } as c_long; - unsafe { - *(ptr.cast::()) = value; - } - Ok(()) - }, - |lua: &Lua, ptr: *mut ()| { - let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; - Ok(value) - }, - )? - .into_lua(lua)?, - ), - ( - "longlong", - CType::new( - Type::c_longlong(), - Some(String::from("longlong")), - |data, ptr| { - let value = match data { - LuaValue::Integer(t) => t, - _ => { - return Err(LuaError::external(format!( - "Integer expected, got {}", - data.type_name() - ))) - } - } as c_longlong; - unsafe { - *(ptr.cast::()) = value; - } - Ok(()) - }, - |lua: &Lua, ptr: *mut ()| { - let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; - Ok(value) - }, - )? - .into_lua(lua)?, - ), - ( - "char", - CType::new( - if CHAR_IS_SIGNED { - Type::c_schar() - } else { - Type::c_uchar() - }, - Some(String::from("char")), - |data, ptr| { - let value = match data { - LuaValue::Integer(t) => t, - _ => { - return Err(LuaError::external(format!( - "Integer expected, got {}", - data.type_name() - ))) - } - } as c_char; - unsafe { - *(ptr.cast::()) = value; - } - Ok(()) - }, - |lua: &Lua, ptr: *mut ()| { - let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; - Ok(value) - }, - )? - .into_lua(lua)?, - ), - ]) -} diff --git a/crates/lune-std-ffi/src/c/types/c_int.rs b/crates/lune-std-ffi/src/c/types/c_int.rs new file mode 100644 index 0000000..3e36a69 --- /dev/null +++ b/crates/lune-std-ffi/src/c/types/c_int.rs @@ -0,0 +1,38 @@ +use core::ffi::c_int; + +use libffi::middle::Type; +use mlua::prelude::*; + +use super::super::c_type::{CType, PtrHandle}; + +impl PtrHandle for CType { + fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> { + let value = match value { + LuaValue::Integer(t) => t, + _ => { + return Err(LuaError::external(format!( + "Integer expected, got {}", + value.type_name() + ))) + } + } as c_int; + unsafe { + *(ptr.cast::()) = value; + } + Ok(()) + } + fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult { + let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; + Ok(value) + } +} + +impl CType { + fn new() -> LuaResult { + Self::new_with_libffi_type(Type::c_int(), Some("int")) + } +} + +pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> { + Ok(("int", lua.create_userdata(CType::::new()?)?)) +} diff --git a/crates/lune-std-ffi/src/c/types/mod.rs b/crates/lune-std-ffi/src/c/types/mod.rs new file mode 100644 index 0000000..0d4986d --- /dev/null +++ b/crates/lune-std-ffi/src/c/types/mod.rs @@ -0,0 +1,8 @@ +mod c_int; + +use mlua::prelude::*; + +// export all default c-types +pub fn create_all_types(lua: &Lua) -> LuaResult> { + Ok(vec![c_int::get_export(lua)?]) +} diff --git a/crates/lune-std-ffi/src/ffi/ffi_helper.rs b/crates/lune-std-ffi/src/ffi/ffi_helper.rs index 87a905e..3e9f48a 100644 --- a/crates/lune-std-ffi/src/ffi/ffi_helper.rs +++ b/crates/lune-std-ffi/src/ffi/ffi_helper.rs @@ -22,7 +22,7 @@ pub unsafe fn get_ptr_from_userdata( } else if userdata.is::() { userdata.borrow::()?.get_ptr() } else { - return Err(LuaError::external("asdf")); + return Err(LuaError::external("Unexpected userdata")); }; let ptr = if let Some(t) = offset { diff --git a/crates/lune-std-ffi/src/ffi/ffi_ref.rs b/crates/lune-std-ffi/src/ffi/ffi_ref.rs index 1150eb1..5e9a9f8 100644 --- a/crates/lune-std-ffi/src/ffi/ffi_ref.rs +++ b/crates/lune-std-ffi/src/ffi/ffi_ref.rs @@ -12,6 +12,8 @@ use super::ffi_bounds::FfiRefBounds; // If it references an area managed by Lua, // the box will remain as long as this reference is alive. +// Todo : how to impl ref == nullptr + pub struct FfiRef { ptr: *mut (), range: Option,