From 6f131e95124ea4de1414417f6a0b59bd46eb4578 Mon Sep 17 00:00:00 2001 From: qwreey Date: Sat, 24 Aug 2024 08:21:28 +0000 Subject: [PATCH] Implement chelper, ffiref, ffibox (#243) --- .../lune-std-ffi/src/{carr.rs => c/c_arr.rs} | 37 ++- crates/lune-std-ffi/src/c/c_cast.rs | 1 + crates/lune-std-ffi/src/{cfn.rs => c/c_fn.rs} | 6 +- crates/lune-std-ffi/src/c/c_helper.rs | 115 +++++++++ .../lune-std-ffi/src/{cptr.rs => c/c_ptr.rs} | 17 +- .../src/{cstring.rs => c/c_string.rs} | 0 .../src/{cstruct.rs => c/c_struct.rs} | 24 +- crates/lune-std-ffi/src/c/c_type.rs | 238 ++++++++++++++++++ crates/lune-std-ffi/src/c/mod.rs | 14 ++ crates/lune-std-ffi/src/ctype.rs | 227 ----------------- .../ffi_association.rs} | 0 crates/lune-std-ffi/src/ffi/ffi_box.rs | 137 ++++++++++ crates/lune-std-ffi/src/ffi/ffi_helper.rs | 35 +++ .../src/{ffilib.rs => ffi/ffi_lib.rs} | 6 +- crates/lune-std-ffi/src/ffi/ffi_platform.rs | 22 ++ .../src/{ffiraw.rs => ffi/ffi_raw.rs} | 3 + crates/lune-std-ffi/src/ffi/ffi_ref.rs | 94 +++++++ crates/lune-std-ffi/src/ffi/mod.rs | 13 + crates/lune-std-ffi/src/ffibox.rs | 87 ------- crates/lune-std-ffi/src/ffiref.rs | 61 ----- crates/lune-std-ffi/src/lib.rs | 34 +-- crates/lune-std-ffi/todo.md | 22 +- 22 files changed, 743 insertions(+), 450 deletions(-) rename crates/lune-std-ffi/src/{carr.rs => c/c_arr.rs} (80%) create mode 100644 crates/lune-std-ffi/src/c/c_cast.rs rename crates/lune-std-ffi/src/{cfn.rs => c/c_fn.rs} (87%) create mode 100644 crates/lune-std-ffi/src/c/c_helper.rs rename crates/lune-std-ffi/src/{cptr.rs => c/c_ptr.rs} (82%) rename crates/lune-std-ffi/src/{cstring.rs => c/c_string.rs} (100%) rename crates/lune-std-ffi/src/{cstruct.rs => c/c_struct.rs} (89%) create mode 100644 crates/lune-std-ffi/src/c/c_type.rs create mode 100644 crates/lune-std-ffi/src/c/mod.rs delete mode 100644 crates/lune-std-ffi/src/ctype.rs rename crates/lune-std-ffi/src/{association.rs => ffi/ffi_association.rs} (100%) create mode 100644 crates/lune-std-ffi/src/ffi/ffi_box.rs create mode 100644 crates/lune-std-ffi/src/ffi/ffi_helper.rs rename crates/lune-std-ffi/src/{ffilib.rs => ffi/ffi_lib.rs} (91%) create mode 100644 crates/lune-std-ffi/src/ffi/ffi_platform.rs rename crates/lune-std-ffi/src/{ffiraw.rs => ffi/ffi_raw.rs} (88%) create mode 100644 crates/lune-std-ffi/src/ffi/ffi_ref.rs create mode 100644 crates/lune-std-ffi/src/ffi/mod.rs delete mode 100644 crates/lune-std-ffi/src/ffibox.rs delete mode 100644 crates/lune-std-ffi/src/ffiref.rs diff --git a/crates/lune-std-ffi/src/carr.rs b/crates/lune-std-ffi/src/c/c_arr.rs similarity index 80% rename from crates/lune-std-ffi/src/carr.rs rename to crates/lune-std-ffi/src/c/c_arr.rs index 886a01f..6fbd964 100644 --- a/crates/lune-std-ffi/src/carr.rs +++ b/crates/lune-std-ffi/src/c/c_arr.rs @@ -1,11 +1,13 @@ use libffi::middle::Type; use mlua::prelude::*; -use crate::association::{get_association, set_association}; -use crate::cptr::CPtr; -use crate::ctype::{ - libffi_type_ensured_size, libffi_type_from_userdata, type_userdata_stringify, CType, +use super::association_names::CARR_INNER; +use super::c_helper::{ + get_ensured_size, name_from_userdata, stringify_userdata, type_from_userdata, }; +use super::c_ptr::CPtr; +use super::c_type::CType; +use crate::ffi::ffi_association::{get_association, set_association}; // This is a series of some type. // It provides the final size and the offset of the index, @@ -18,8 +20,6 @@ use crate::ctype::{ // Padding after each field inside the struct is set to next field can follow the alignment. // There is no problem even if you create a struct with n fields of a single type within the struct. Array adheres to the condition that there is no additional padding between each element. Padding to a struct is padding inside the struct. Simply think of the padding byte as a trailing unnamed field. -const CARR_INNER: &str = "__carr_inner"; - pub struct CArr { libffi_type: Type, struct_type: Type, @@ -31,7 +31,7 @@ pub struct CArr { impl CArr { pub fn new(libffi_type: Type, length: usize) -> LuaResult { let struct_type = Type::structure(vec![libffi_type.clone(); length]); - let field_size = libffi_type_ensured_size(libffi_type.as_raw_ptr())?; + let field_size = get_ensured_size(libffi_type.as_raw_ptr())?; Ok(Self { libffi_type, @@ -47,7 +47,7 @@ impl CArr { luatype: &LuaAnyUserData<'lua>, length: usize, ) -> LuaResult> { - let fields = libffi_type_from_userdata(luatype)?; + let fields = type_from_userdata(luatype)?; let carr = lua.create_userdata(Self::new(fields, length)?)?; set_association(lua, CARR_INNER, carr.clone(), luatype)?; @@ -63,15 +63,26 @@ impl CArr { pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult { let inner: LuaValue = userdata.get("inner")?; let carr = userdata.borrow::()?; + if inner.is_userdata() { let inner = inner .as_userdata() .ok_or(LuaError::external("failed to get inner type userdata."))?; - Ok(format!( - " {} ; {} ", - type_userdata_stringify(inner)?, - carr.length - )) + + if inner.is::() { + Ok(format!( + " {} ; {} ", + stringify_userdata(inner)?, + carr.length + )) + } else { + Ok(format!( + " <{}({})> ; {} ", + name_from_userdata(inner), + stringify_userdata(inner)?, + carr.length + )) + } } else { Err(LuaError::external("failed to get inner type userdata.")) } diff --git a/crates/lune-std-ffi/src/c/c_cast.rs b/crates/lune-std-ffi/src/c/c_cast.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/lune-std-ffi/src/c/c_cast.rs @@ -0,0 +1 @@ + diff --git a/crates/lune-std-ffi/src/cfn.rs b/crates/lune-std-ffi/src/c/c_fn.rs similarity index 87% rename from crates/lune-std-ffi/src/cfn.rs rename to crates/lune-std-ffi/src/c/c_fn.rs index f029cfc..315497e 100644 --- a/crates/lune-std-ffi/src/cfn.rs +++ b/crates/lune-std-ffi/src/c/c_fn.rs @@ -1,7 +1,7 @@ use libffi::middle::{Cif, Type}; use mlua::prelude::*; -use crate::ctype::{libffi_type_from_userdata, libffi_types_from_table}; +use super::c_helper::{type_from_userdata, type_list_from_table}; // cfn is a type declaration for a function. // Basically, when calling an external function, this type declaration @@ -36,8 +36,8 @@ impl CFn { } pub fn from_lua_table(args: LuaTable, ret: LuaAnyUserData) -> LuaResult { - let args = libffi_types_from_table(&args)?; - let ret = libffi_type_from_userdata(&ret)?; + let args = type_list_from_table(&args)?; + let ret = type_from_userdata(&ret)?; Ok(Self::new(args, ret)) } } diff --git a/crates/lune-std-ffi/src/c/c_helper.rs b/crates/lune-std-ffi/src/c/c_helper.rs new file mode 100644 index 0000000..d25843c --- /dev/null +++ b/crates/lune-std-ffi/src/c/c_helper.rs @@ -0,0 +1,115 @@ +use std::ptr::{self, null_mut}; + +use libffi::{low, middle::Type, raw}; +use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; +use mlua::prelude::*; + +use super::c_arr::CArr; +use super::c_ptr::CPtr; +use super::c_struct::CStruct; +use super::c_type::CType; +use crate::ffi::ffi_helper::FFI_STATUS_NAMES; + +// get Vec from table(array) of c-types userdata +pub fn type_list_from_table(table: &LuaTable) -> LuaResult> { + let len: usize = table.raw_len(); + let mut fields = Vec::with_capacity(len); + + for i in 0..len { + // Test required + let value = table.raw_get(i + 1)?; + match value { + LuaValue::UserData(field_type) => { + fields.push(type_from_userdata(&field_type)?); + } + _ => { + return Err(LuaError::external(format!( + "Unexpected field. CStruct, CType or CArr is required for element but got {}", + pretty_format_value(&value, &ValueFormatConfig::new()) + ))); + } + } + } + + Ok(fields) +} + +// 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()) + } else if userdata.is::() { + Ok(userdata.borrow::()?.get_type()) + } else if userdata.is::() { + Ok(CPtr::get_type()) + } else { + Err(LuaError::external(format!( + "Unexpected field. CStruct, CType, CString or CArr is required for element but got {}", + pretty_format_value( + // Since the data is in the Lua location, + // there is no problem with the clone. + &LuaValue::UserData(userdata.to_owned()), + &ValueFormatConfig::new() + ) + ))) + } +} + +// stringify any c-type userdata (for recursive) +pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult { + if userdata.is::() { + let name = userdata.borrow::()?.stringify(); + Ok(name) + } else if userdata.is::() { + let name = CStruct::stringify(userdata)?; + Ok(name) + } else if userdata.is::() { + let name = CArr::stringify(userdata)?; + Ok(name) + } else if userdata.is::() { + let name: String = CPtr::stringify(userdata)?; + Ok(name) + } else { + Ok(String::from("unnamed")) + } +} + +// get name tag for any c-type userdata +pub fn name_from_userdata(userdata: &LuaAnyUserData) -> String { + if userdata.is::() { + String::from("CStruct") + } else if userdata.is::() { + String::from("CType") + } else if userdata.is::() { + String::from("CArr") + } else if userdata.is::() { + String::from("CPtr") + } else { + String::from("unnamed") + } +} + +// Ensure sizeof c-type (raw::libffi_type) +// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html +pub fn get_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult { + let mut cif = low::ffi_cif::default(); + let result = unsafe { + raw::ffi_prep_cif( + ptr::from_mut(&mut cif), + raw::ffi_abi_FFI_DEFAULT_ABI, + 0, + ffi_type, + null_mut(), + ) + }; + + if result != raw::ffi_status_FFI_OK { + return Err(LuaError::external(format!( + "ffi_get_struct_offsets failed. expected result {}, got {}", + FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize] + ))); + } + unsafe { Ok((*ffi_type).size) } +} diff --git a/crates/lune-std-ffi/src/cptr.rs b/crates/lune-std-ffi/src/c/c_ptr.rs similarity index 82% rename from crates/lune-std-ffi/src/cptr.rs rename to crates/lune-std-ffi/src/c/c_ptr.rs index 62324d1..5fb8845 100644 --- a/crates/lune-std-ffi/src/cptr.rs +++ b/crates/lune-std-ffi/src/c/c_ptr.rs @@ -5,11 +5,10 @@ use std::borrow::Borrow; use libffi::middle::Type; use mlua::prelude::*; -use crate::association::{get_association, set_association}; -use crate::carr::CArr; -use crate::ctype::{type_name_from_userdata, type_userdata_stringify}; - -const POINTER_INNER: &str = "__pointer_inner"; +use super::association_names::CPTR_INNER; +use super::c_arr::CArr; +use super::c_helper::{name_from_userdata, stringify_userdata}; +use crate::ffi::ffi_association::{get_association, set_association}; pub struct CPtr(); @@ -22,7 +21,7 @@ impl CPtr { ) -> LuaResult> { let value = Self().into_lua(lua)?; - set_association(lua, POINTER_INNER, value.borrow(), inner)?; + set_association(lua, CPTR_INNER, value.borrow(), inner)?; Ok(value) } @@ -37,8 +36,8 @@ impl CPtr { .ok_or(LuaError::external("failed to get inner type userdata."))?; Ok(format!( " <{}({})> ", - type_name_from_userdata(inner), - type_userdata_stringify(inner)?, + name_from_userdata(inner), + stringify_userdata(inner)?, )) } else { Err(LuaError::external("failed to get inner type userdata.")) @@ -55,7 +54,7 @@ impl LuaUserData for CPtr { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fields.add_field_method_get("size", |_, _| Ok(size_of::())); fields.add_field_function_get("inner", |lua, this| { - let inner = get_association(lua, POINTER_INNER, this)? + let inner = get_association(lua, CPTR_INNER, this)? .ok_or(LuaError::external("inner type not found"))?; Ok(inner) }); diff --git a/crates/lune-std-ffi/src/cstring.rs b/crates/lune-std-ffi/src/c/c_string.rs similarity index 100% rename from crates/lune-std-ffi/src/cstring.rs rename to crates/lune-std-ffi/src/c/c_string.rs diff --git a/crates/lune-std-ffi/src/cstruct.rs b/crates/lune-std-ffi/src/c/c_struct.rs similarity index 89% rename from crates/lune-std-ffi/src/cstruct.rs rename to crates/lune-std-ffi/src/c/c_struct.rs index 9a554da..9e945ec 100644 --- a/crates/lune-std-ffi/src/cstruct.rs +++ b/crates/lune-std-ffi/src/c/c_struct.rs @@ -9,13 +9,13 @@ use libffi::{ }; use mlua::prelude::*; -use crate::ctype::{libffi_types_from_table, type_userdata_stringify, CType}; -use crate::FFI_STATUS_NAMES; -use crate::{ - association::{get_association, set_association}, - ctype::type_name_from_userdata, -}; -use crate::{carr::CArr, cptr::CPtr}; +use super::association_names::CSTRUCT_INNER; +use super::c_arr::CArr; +use super::c_helper::{name_from_userdata, stringify_userdata, type_list_from_table}; +use super::c_ptr::CPtr; +use super::c_type::CType; +use crate::ffi::ffi_association::{get_association, set_association}; +use crate::ffi::ffi_helper::FFI_STATUS_NAMES; pub struct CStruct { libffi_cif: Cif, @@ -25,8 +25,6 @@ pub struct CStruct { size: usize, } -const CSTRUCT_INNER: &str = "__cstruct_inner"; - impl CStruct { pub fn new(fields: Vec) -> LuaResult { let libffi_type = Type::structure(fields.clone()); @@ -68,7 +66,7 @@ impl CStruct { lua: &'lua Lua, table: LuaTable<'lua>, ) -> LuaResult> { - let fields = libffi_types_from_table(&table)?; + let fields = type_list_from_table(&table)?; let cstruct = lua.create_userdata(Self::new(fields)?)?; table.set_readonly(true); set_association(lua, CSTRUCT_INNER, cstruct.clone(), table)?; @@ -88,13 +86,13 @@ impl CStruct { for i in 0..table.raw_len() { let child: LuaAnyUserData = table.raw_get(i + 1)?; if child.is::() { - result.push_str(format!("{}, ", type_userdata_stringify(&child)?).as_str()); + result.push_str(format!("{}, ", stringify_userdata(&child)?).as_str()); } else { result.push_str( format!( "<{}({})>, ", - type_name_from_userdata(&child), - type_userdata_stringify(&child)? + name_from_userdata(&child), + stringify_userdata(&child)? ) .as_str(), ); diff --git a/crates/lune-std-ffi/src/c/c_type.rs b/crates/lune-std-ffi/src/c/c_type.rs new file mode 100644 index 0000000..58d3364 --- /dev/null +++ b/crates/lune-std-ffi/src/c/c_type.rs @@ -0,0 +1,238 @@ +#![allow(clippy::cargo_common_metadata)] + +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::{Cif, Type}; +use mlua::prelude::*; + +use super::c_arr::CArr; +use super::c_helper::get_ensured_size; +use super::c_ptr::CPtr; +use crate::ffi::ffi_helper::get_ptr_from_userdata; +use crate::ffi::ffi_platform::CHAR_IS_SIGNED; +// use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw}; + +pub struct CType { + 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 c_void) -> LuaResult<()>, + + // Read luavalue from some ptr + pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult, +} + +impl CType { + pub fn new( + libffi_type: Type, + name: Option, + luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>, + ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult, + ) -> LuaResult { + let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void()); + let size = get_ensured_size(libffi_type.as_raw_ptr())?; + Ok(Self { + libffi_cif: libffi_cfi, + libffi_type, + size, + name, + luavalue_into_ptr, + ptr_into_luavalue, + }) + } + + pub fn get_type(&self) -> Type { + self.libffi_type.clone() + } + + pub fn stringify(&self) -> String { + match &self.name { + Some(t) => t.to_owned(), + None => String::from("unnamed"), + } + } + + // Read data from ptr and convert it into luavalue + pub unsafe fn read_ptr<'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)?; + Ok(value) + } + + // Write converted data from luavalue into ptr + pub unsafe fn write_ptr<'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)?; + Ok(()) + } +} + +impl LuaUserData for CType { + 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) + }); + methods.add_method( + "from", + |lua, ctype, (userdata, offset): (LuaAnyUserData, Option)| { + let value = unsafe { ctype.read_ptr(lua, userdata, offset)? }; + Ok(value) + }, + ); + methods.add_method( + "into", + |_, ctype, (value, userdata, offset): (LuaValue, LuaAnyUserData, Option)| { + unsafe { ctype.write_ptr(value, userdata, offset)? }; + Ok(()) + }, + ); + methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| { + let carr = CArr::from_lua_userdata(lua, &this, length)?; + Ok(carr) + }); + methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| { + let name = this.stringify(); + Ok(name) + }); + } +} + +// 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 c_void| { + 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 c_void| { + 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 c_void| { + 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 c_void| { + let value = unsafe { (*ptr.cast::()).into_lua(lua)? }; + Ok(value) + }, + )? + .into_lua(lua)?, + ), + ]) +} diff --git a/crates/lune-std-ffi/src/c/mod.rs b/crates/lune-std-ffi/src/c/mod.rs new file mode 100644 index 0000000..803fa62 --- /dev/null +++ b/crates/lune-std-ffi/src/c/mod.rs @@ -0,0 +1,14 @@ +pub(super) mod c_arr; +pub(super) mod c_fn; +pub(super) mod c_helper; +pub(super) mod c_ptr; +pub(super) mod c_string; +pub(super) mod c_struct; +pub(super) mod c_type; + +// Named registry table names +mod association_names { + pub const CPTR_INNER: &str = "__cptr_inner"; + pub const CARR_INNER: &str = "__carr_inner"; + pub const CSTRUCT_INNER: &str = "__cstruct_inner"; +} diff --git a/crates/lune-std-ffi/src/ctype.rs b/crates/lune-std-ffi/src/ctype.rs deleted file mode 100644 index 7fe6b15..0000000 --- a/crates/lune-std-ffi/src/ctype.rs +++ /dev/null @@ -1,227 +0,0 @@ -#![allow(clippy::cargo_common_metadata)] - -use std::borrow::Borrow; -use std::ptr::{self, null_mut}; - -use libffi::{ - low, - middle::{Cif, Type}, - raw, -}; -use lune_utils::fmt::{pretty_format_value, ValueFormatConfig}; -use mlua::prelude::*; - -use crate::association::{get_association, set_association}; -use crate::carr::CArr; -use crate::cptr::CPtr; -use crate::cstruct::CStruct; -use crate::FFI_STATUS_NAMES; -// use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw}; - -const POINTER_INNER: &str = "__pointer_inner"; - -pub struct CType { - libffi_cif: Cif, - libffi_type: Type, - size: usize, - name: Option, -} - -impl CType { - pub fn new(libffi_type: Type, name: Option) -> LuaResult { - let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void()); - let size = libffi_type_ensured_size(libffi_type.as_raw_ptr())?; - Ok(Self { - libffi_cif: libffi_cfi, - libffi_type, - size, - name, - }) - } - - pub fn get_type(&self) -> Type { - self.libffi_type.clone() - } - - pub fn stringify(&self) -> String { - match &self.name { - Some(t) => t.to_owned(), - None => String::from("unnamed"), - } - } -} - -impl LuaUserData for CType { - 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) - }); - methods.add_function("arr", |lua, (this, length): (LuaAnyUserData, usize)| { - let carr = CArr::from_lua_userdata(lua, &this, length)?; - Ok(carr) - }); - methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| { - let name = this.stringify(); - Ok(name) - }); - } -} - -// export all default c-types -pub fn create_all_types(lua: &Lua) -> LuaResult> { - Ok(vec![ - ( - "u8", - CType::new(Type::u8(), Some(String::from("u8")))?.into_lua(lua)?, - ), - ( - "u16", - CType::new(Type::u16(), Some(String::from("u16")))?.into_lua(lua)?, - ), - ( - "u32", - CType::new(Type::u32(), Some(String::from("u32")))?.into_lua(lua)?, - ), - ( - "u64", - CType::new(Type::u64(), Some(String::from("u64")))?.into_lua(lua)?, - ), - ( - "i8", - CType::new(Type::i8(), Some(String::from("i8")))?.into_lua(lua)?, - ), - ( - "i16", - CType::new(Type::i16(), Some(String::from("i16")))?.into_lua(lua)?, - ), - ( - "i32", - CType::new(Type::i32(), Some(String::from("i32")))?.into_lua(lua)?, - ), - ( - "i64", - CType::new(Type::i64(), Some(String::from("i64")))?.into_lua(lua)?, - ), - ( - "f32", - CType::new(Type::f32(), Some(String::from("f32")))?.into_lua(lua)?, - ), - ( - "f64", - CType::new(Type::f64(), Some(String::from("f64")))?.into_lua(lua)?, - ), - ( - "void", - CType::new(Type::void(), Some(String::from("void")))?.into_lua(lua)?, - ), - ]) -} - -// get Vec from table(array) of c-types userdata -pub fn libffi_types_from_table(table: &LuaTable) -> LuaResult> { - let len: usize = table.raw_len(); - let mut fields = Vec::with_capacity(len); - - for i in 0..len { - // Test required - let value = table.raw_get(i + 1)?; - match value { - LuaValue::UserData(field_type) => { - fields.push(libffi_type_from_userdata(&field_type)?); - } - _ => { - return Err(LuaError::external(format!( - "Unexpected field. CStruct, CType or CArr is required for element but got {}", - pretty_format_value(&value, &ValueFormatConfig::new()) - ))); - } - } - } - - Ok(fields) -} - -// get libffi_type from any c-type userdata -pub fn libffi_type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult { - if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) - } else if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) - } else if userdata.is::() { - Ok(userdata.borrow::()?.get_type()) - } else if userdata.is::() { - Ok(CPtr::get_type()) - } else { - Err(LuaError::external(format!( - "Unexpected field. CStruct, CType, CString or CArr is required for element but got {}", - pretty_format_value( - // Since the data is in the Lua location, - // there is no problem with the clone. - &LuaValue::UserData(userdata.to_owned()), - &ValueFormatConfig::new() - ) - ))) - } -} - -// stringify any c-type userdata (for recursive) -pub fn type_userdata_stringify(userdata: &LuaAnyUserData) -> LuaResult { - if userdata.is::() { - let name = userdata.borrow::()?.stringify(); - Ok(name) - } else if userdata.is::() { - let name = CStruct::stringify(userdata)?; - Ok(name) - } else if userdata.is::() { - let name = CArr::stringify(userdata)?; - Ok(name) - } else if userdata.is::() { - let name: String = CPtr::stringify(userdata)?; - Ok(name) - } else { - Ok(String::from("unnamed")) - } -} - -// get name tag for any c-type userdata -pub fn type_name_from_userdata(userdata: &LuaAnyUserData) -> String { - if userdata.is::() { - String::from("CStruct") - } else if userdata.is::() { - String::from("CType") - } else if userdata.is::() { - String::from("CArr") - } else if userdata.is::() { - String::from("CPtr") - } else { - String::from("unnamed") - } -} - -// Ensure sizeof c-type (raw::libffi_type) -// See: http://www.chiark.greenend.org.uk/doc/libffi-dev/html/Size-and-Alignment.html -pub fn libffi_type_ensured_size(ffi_type: *mut raw::ffi_type) -> LuaResult { - let mut cif: low::ffi_cif = Default::default(); - let result = unsafe { - raw::ffi_prep_cif( - ptr::from_mut(&mut cif), - raw::ffi_abi_FFI_DEFAULT_ABI, - 0, - ffi_type, - null_mut(), - ) - }; - - if result != raw::ffi_status_FFI_OK { - return Err(LuaError::external(format!( - "ffi_get_struct_offsets failed. expected result {}, got {}", - FFI_STATUS_NAMES[0], FFI_STATUS_NAMES[result as usize] - ))); - } - unsafe { Ok((*ffi_type).size) } -} diff --git a/crates/lune-std-ffi/src/association.rs b/crates/lune-std-ffi/src/ffi/ffi_association.rs similarity index 100% rename from crates/lune-std-ffi/src/association.rs rename to crates/lune-std-ffi/src/ffi/ffi_association.rs diff --git a/crates/lune-std-ffi/src/ffi/ffi_box.rs b/crates/lune-std-ffi/src/ffi/ffi_box.rs new file mode 100644 index 0000000..49fb1d2 --- /dev/null +++ b/crates/lune-std-ffi/src/ffi/ffi_box.rs @@ -0,0 +1,137 @@ +#![allow(clippy::cargo_common_metadata)] + +// It is an untyped, sized memory area that Lua can manage. +// This area is safe within Lua. Operations have their boundaries checked. +// It is basically intended to implement passing a pointed space to the outside. +// It also helps you handle data that Lua cannot handle. +// Depending on the type, operations such as sum, mul, and mod may be implemented. +// There is no need to enclose all data in a box; +// rather, it creates more heap space, so it should be used appropriately +// where necessary. + +use std::boxed::Box; + +use core::ffi::c_void; +use mlua::prelude::*; + +use super::association_names::BOX_REF_INNER; +use super::ffi_association::set_association; +use super::ffi_ref::FfiRange; +use super::ffi_ref::FfiRef; + +pub struct FfiBox(Box<[u8]>); + +impl FfiBox { + // For efficiency, it is initialized non-zeroed. + pub fn new(size: usize) -> Self { + // Create new vector to allocate heap memory. sized with 'size' + let mut vec_heap = Vec::::with_capacity(size); + + // It is safe to have a length equal to the capacity + #[allow(clippy::uninit_vec)] + unsafe { + vec_heap.set_len(size); + } + + Self(vec_heap.into_boxed_slice()) + } + + pub fn size(&self) -> usize { + self.0.len() + } + + // pub fn copy(&self, target: &mut FfiBox) {} + + pub fn get_ptr(&self) -> *mut c_void { + self.0.as_ptr() as *mut c_void + } + + pub fn stringify(&self) -> String { + let mut buff = String::from(" "); + for i in &self.0 { + buff.push_str(i.to_string().as_str()); + buff.push_str(", "); + } + buff.pop(); + buff.pop(); + buff.push(' '); + buff + } + + pub fn binary_print(&self) -> String { + let mut buff: String = String::with_capacity(self.size() * 10 - 2); + for (pos, value) in self.0.iter().enumerate() { + for i in 0..8 { + if (value & (1 << i)) == 0 { + buff.push('0'); + } else { + buff.push('1'); + } + } + if pos < self.size() - 1 { + buff.push_str(", "); + } + } + buff + } + + // bad naming. i have no idea what should i use + pub fn luaref<'lua>( + lua: &'lua Lua, + this: LuaAnyUserData<'lua>, + offset: Option, + ) -> LuaResult> { + let target = this.borrow::()?; + let ptr = if let Some(t) = offset { + if t < 0 || t >= (target.size() as isize) { + return Err(LuaError::external(format!( + "Offset is out of bounds. box.size: {}. offset got {}", + target.size(), + t + ))); + } + unsafe { target.get_ptr().offset(t) } + } else { + target.get_ptr() + }; + + let luaref = lua.create_userdata(FfiRef::new( + ptr, + Some(FfiRange { + low: 0, + high: target.size() as isize, + }), + ))?; + + set_association(lua, BOX_REF_INNER, luaref.clone(), this.clone())?; + + Ok(luaref) + } + + pub fn zero(&mut self) { + self.0.fill(0u8); + } +} + +impl LuaUserData for FfiBox { + 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_mut("zero", |_, this: LuaAnyUserData| { + this.borrow_mut::()?.zero(); + Ok(this) + }); + methods.add_function( + "ref", + |lua, (this, offset): (LuaAnyUserData, Option)| { + let luaref = FfiBox::luaref(lua, this, offset)?; + Ok(luaref) + }, + ); + methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| { + Ok(this.binary_print()) + }); + } +} diff --git a/crates/lune-std-ffi/src/ffi/ffi_helper.rs b/crates/lune-std-ffi/src/ffi/ffi_helper.rs new file mode 100644 index 0000000..ffa32f2 --- /dev/null +++ b/crates/lune-std-ffi/src/ffi/ffi_helper.rs @@ -0,0 +1,35 @@ +use std::ffi::c_void; + +use mlua::prelude::*; + +use super::ffi_box::FfiBox; +use super::ffi_ref::FfiRef; + +// Converts ffi status into &str +pub const FFI_STATUS_NAMES: [&str; 4] = [ + "ffi_status_FFI_OK", + "ffi_status_FFI_BAD_TYPEDEF", + "ffi_status_FFI_BAD_ABI", + "ffi_status_FFI_BAD_ARGTYPE", +]; + +pub unsafe fn get_ptr_from_userdata( + userdata: &LuaAnyUserData, + offset: Option, +) -> LuaResult<*mut c_void> { + let ptr = if userdata.is::() { + userdata.borrow::()?.get_ptr() + } else if userdata.is::() { + userdata.borrow::()?.get_ptr() + } else { + return Err(LuaError::external("asdf")); + }; + + let ptr = if let Some(t) = offset { + ptr.offset(t) + } else { + ptr + }; + + Ok(ptr) +} diff --git a/crates/lune-std-ffi/src/ffilib.rs b/crates/lune-std-ffi/src/ffi/ffi_lib.rs similarity index 91% rename from crates/lune-std-ffi/src/ffilib.rs rename to crates/lune-std-ffi/src/ffi/ffi_lib.rs index 2395868..bf87015 100644 --- a/crates/lune-std-ffi/src/ffilib.rs +++ b/crates/lune-std-ffi/src/ffi/ffi_lib.rs @@ -3,8 +3,8 @@ use std::ffi::c_void; use dlopen2::symbor::Library; use mlua::prelude::*; -use crate::association::set_association; -use crate::ffiref::FfiRef; +use super::ffi_association::set_association; +use super::ffi_ref::FfiRef; pub struct FfiLib(Library); @@ -39,7 +39,7 @@ impl FfiLib { .map_err(|err| LuaError::external(format!("{err}")))? }; - let luasym = lua.create_userdata(FfiRef::new(*sym))?; + let luasym = lua.create_userdata(FfiRef::new(*sym, None))?; set_association(lua, SYM_INNER, luasym.clone(), this.clone())?; diff --git a/crates/lune-std-ffi/src/ffi/ffi_platform.rs b/crates/lune-std-ffi/src/ffi/ffi_platform.rs new file mode 100644 index 0000000..c7371aa --- /dev/null +++ b/crates/lune-std-ffi/src/ffi/ffi_platform.rs @@ -0,0 +1,22 @@ +use core::ffi::c_char; +use std::env::consts; +use std::vec::Vec; + +pub const CHAR_IS_SIGNED: bool = c_char::MIN as u8 != u8::MIN; +pub const IS_LITTLE_ENDIAN: bool = cfg!(target_endian = "little"); + +pub fn get_platform_value() -> Vec<(&'static str, &'static str)> { + vec![ + // https://doc.rust-lang.org/std/env/consts/constant.ARCH.html + ("arch", consts::ARCH), + // https://doc.rust-lang.org/std/env/consts/constant.OS.html + ("os", consts::OS), + // https://doc.rust-lang.org/std/env/consts/constant.FAMILY.html + ("family", consts::FAMILY), + ("endian", if IS_LITTLE_ENDIAN { "little" } else { "big" }), + ( + "char_variant", + if CHAR_IS_SIGNED { "schar" } else { "uchar" }, + ), + ] +} diff --git a/crates/lune-std-ffi/src/ffiraw.rs b/crates/lune-std-ffi/src/ffi/ffi_raw.rs similarity index 88% rename from crates/lune-std-ffi/src/ffiraw.rs rename to crates/lune-std-ffi/src/ffi/ffi_raw.rs index 6d64e58..6a82cd9 100644 --- a/crates/lune-std-ffi/src/ffiraw.rs +++ b/crates/lune-std-ffi/src/ffi/ffi_raw.rs @@ -1,3 +1,6 @@ +use core::ffi::c_void; +use std::{convert, mem::transmute, ptr}; + // This is raw data coming from outside. // Users must convert it to a Lua value, reference, or box to use it. // The biggest reason for providing this is to allow the user to diff --git a/crates/lune-std-ffi/src/ffi/ffi_ref.rs b/crates/lune-std-ffi/src/ffi/ffi_ref.rs new file mode 100644 index 0000000..a5ebc70 --- /dev/null +++ b/crates/lune-std-ffi/src/ffi/ffi_ref.rs @@ -0,0 +1,94 @@ +use core::ffi::c_void; +use std::ptr; + +use mlua::prelude::*; + +use super::association_names::REF_INNER; +use super::ffi_association::set_association; + +// A referenced space. It is possible to read and write through types. +// This operation is not safe. This may cause a memory error in Lua +// if use it incorrectly. +// If it references an area managed by Lua, +// the box will remain as long as this reference is alive. + +pub struct FfiRange { + pub(crate) high: isize, + pub(crate) low: isize, +} + +pub struct FfiRef { + ptr: *mut c_void, + range: Option, +} + +impl FfiRef { + pub fn new(ptr: *mut c_void, range: Option) -> Self { + Self { ptr, range } + } + + // bad naming. i have no idea what should i use + pub fn luaref<'lua>( + lua: &'lua Lua, + this: LuaAnyUserData<'lua>, + ) -> LuaResult> { + let target = this.borrow::()?; + + let luaref = lua.create_userdata(FfiRef::new( + ptr::from_ref(&target.ptr) as *mut c_void, + Some(FfiRange { + low: 0, + high: size_of::() as isize, + }), + ))?; + + set_association(lua, REF_INNER, luaref.clone(), this.clone())?; + + Ok(luaref) + } + + pub fn get_ptr(&self) -> *mut c_void { + self.ptr + } + + pub unsafe fn deref(&self) -> Self { + Self::new(*self.ptr.cast::<*mut c_void>(), None) + } + + pub unsafe fn offset(&self, offset: isize) -> LuaResult { + let range = if let Some(ref t) = self.range { + let high = t.high - offset; + let low = t.low - offset; + + if low > 0 || high < 0 { + return Err(LuaError::external(format!( + "Offset is out of bounds. low: {}, high: {}. offset got {}", + t.low, t.high, offset + ))); + } + + Some(FfiRange { high, low }) + } else { + None + }; + + Ok(Self::new(self.ptr.offset(offset), range)) + } +} + +impl LuaUserData for FfiRef { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("deref", |_, this, ()| { + let ffiref = unsafe { this.deref() }; + Ok(ffiref) + }); + methods.add_method("offset", |_, this, offset: isize| { + let ffiref = unsafe { this.offset(offset)? }; + Ok(ffiref) + }); + methods.add_function("ref", |lua, this: LuaAnyUserData| { + let ffiref = FfiRef::luaref(lua, this)?; + Ok(ffiref) + }); + } +} diff --git a/crates/lune-std-ffi/src/ffi/mod.rs b/crates/lune-std-ffi/src/ffi/mod.rs new file mode 100644 index 0000000..4812028 --- /dev/null +++ b/crates/lune-std-ffi/src/ffi/mod.rs @@ -0,0 +1,13 @@ +pub(super) mod ffi_association; +pub(super) mod ffi_box; +pub(super) mod ffi_helper; +pub(super) mod ffi_lib; +pub(super) mod ffi_platform; +pub(super) mod ffi_raw; +pub(super) mod ffi_ref; + +// Named registry table names +mod association_names { + pub const BOX_REF_INNER: &str = "__box_ref"; + pub const REF_INNER: &str = "__ref_inner"; +} diff --git a/crates/lune-std-ffi/src/ffibox.rs b/crates/lune-std-ffi/src/ffibox.rs deleted file mode 100644 index b9d0df8..0000000 --- a/crates/lune-std-ffi/src/ffibox.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![allow(clippy::cargo_common_metadata)] - -// It is an untyped, sized memory area that Lua can manage. -// This area is safe within Lua. Operations have their boundaries checked. -// It is basically intended to implement passing a pointed space to the outside. -// It also helps you handle data that Lua cannot handle. -// Depending on the type, operations such as sum, mul, and mod may be implemented. -// There is no need to enclose all data in a box; -// rather, it creates more heap space, so it should be used appropriately -// where necessary. - -use std::boxed::Box; - -use core::ffi::c_void; -use mlua::prelude::*; - -use crate::association::set_association; -use crate::ffiref::FfiRef; - -const BOX_REF_INNER: &str = "__box_ref"; - -pub struct FfiBox(Box<[u8]>); - -impl FfiBox { - pub fn new(size: usize) -> Self { - Self(vec![0u8; size].into_boxed_slice()) - } - - pub fn size(&self) -> usize { - self.0.len() - } - - // pub fn copy(&self, target: &mut FfiBox) {} - - pub fn get_ptr(&self) -> *mut c_void { - self.0.as_ptr() as *mut c_void - } - - // bad naming. i have no idea what should i use - pub fn luaref<'lua>( - lua: &'lua Lua, - this: LuaAnyUserData<'lua>, - ) -> LuaResult> { - let target = this.borrow::()?; - - let luaref = lua.create_userdata(FfiRef::new(target.get_ptr()))?; - - set_association(lua, BOX_REF_INNER, luaref.clone(), this.clone())?; - - Ok(luaref) - } - - pub fn zero(&mut self) { - self.0.fill(0u8); - } -} - -impl LuaUserData for FfiBox { - 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_method_mut("zero", |_, this, ()| { - this.zero(); - Ok(()) - }); - methods.add_function("ref", |lua, this: LuaAnyUserData| { - let luaref = FfiBox::luaref(lua, this)?; - Ok(luaref) - }); - methods.add_meta_method(LuaMetaMethod::Len, |_, this, ()| Ok(this.size())); - methods.add_meta_method(LuaMetaMethod::ToString, |lua, this, ()| { - dbg!(&this.0.len()); - let mut buff = String::from("[ "); - for i in &this.0 { - buff.push_str(i.to_owned().to_string().as_str()); - buff.push_str(", "); - } - buff.pop(); - buff.pop(); - buff.push_str(" ]"); - let luastr = lua.create_string(buff.as_bytes())?; - Ok(luastr) - }); - } -} diff --git a/crates/lune-std-ffi/src/ffiref.rs b/crates/lune-std-ffi/src/ffiref.rs deleted file mode 100644 index 79473fa..0000000 --- a/crates/lune-std-ffi/src/ffiref.rs +++ /dev/null @@ -1,61 +0,0 @@ -use core::ffi::c_void; -use std::ptr; - -use mlua::prelude::*; - -use crate::association::set_association; - -// A referenced space. It is possible to read and write through types. -// This operation is not safe. This may cause a memory error in Lua -// if use it incorrectly. -// If it references an area managed by Lua, -// the box will remain as long as this reference is alive. - -pub struct FfiRef(*mut c_void); - -const REF_INNER: &str = "__ref_inner"; - -impl FfiRef { - pub fn new(target: *mut c_void) -> Self { - Self(target) - } - - // bad naming. i have no idea what should i use - pub fn luaref<'lua>( - lua: &'lua Lua, - this: LuaAnyUserData<'lua>, - ) -> LuaResult> { - let target = this.borrow::()?; - - let luaref = lua.create_userdata(FfiRef::new(ptr::from_ref(&target.0) as *mut c_void))?; - - set_association(lua, REF_INNER, luaref.clone(), this.clone())?; - - Ok(luaref) - } - - pub unsafe fn deref(&self) -> Self { - Self::new(*self.0.cast::<*mut c_void>()) - } - - pub unsafe fn offset(&self, offset: isize) -> Self { - Self::new(self.0.offset(offset)) - } -} - -impl LuaUserData for FfiRef { - fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_method("deref", |_, this, ()| { - let ffiref = unsafe { this.deref() }; - Ok(ffiref) - }); - methods.add_method("offset", |_, this, offset: isize| { - let ffiref = unsafe { this.offset(offset) }; - Ok(ffiref) - }); - methods.add_function("ref", |lua, this: LuaAnyUserData| { - let ffiref = FfiRef::luaref(lua, this)?; - Ok(ffiref) - }); - } -} diff --git a/crates/lune-std-ffi/src/lib.rs b/crates/lune-std-ffi/src/lib.rs index a8a5adc..1bcfbe0 100644 --- a/crates/lune-std-ffi/src/lib.rs +++ b/crates/lune-std-ffi/src/lib.rs @@ -3,31 +3,16 @@ use lune_utils::TableBuilder; use mlua::prelude::*; -mod association; -mod carr; -mod cfn; -mod cptr; -mod cstring; -mod cstruct; -mod ctype; -mod ffibox; -mod ffilib; -mod ffiraw; -mod ffiref; +mod c; +mod ffi; -use crate::association::get_table; -use crate::cfn::CFn; -use crate::cstruct::CStruct; -use crate::ctype::create_all_types; -use crate::ffibox::FfiBox; -use crate::ffilib::FfiLib; - -pub const FFI_STATUS_NAMES: [&str; 4] = [ - "ffi_status_FFI_OK", - "ffi_status_FFI_BAD_TYPEDEF", - "ffi_status_FFI_BAD_ABI", - "ffi_status_FFI_BAD_ARGTYPE", -]; +use crate::c::c_fn::CFn; +use crate::c::c_struct::CStruct; +use crate::c::c_type::create_all_types; +use crate::ffi::ffi_association::get_table; +use crate::ffi::ffi_box::FfiBox; +use crate::ffi::ffi_lib::FfiLib; +use crate::ffi::ffi_platform::get_platform_value; /** Creates the `ffi` standard library module. @@ -40,6 +25,7 @@ pub fn module(lua: &Lua) -> LuaResult { let ctypes = create_all_types(lua)?; let result = TableBuilder::new(lua)? .with_values(ctypes)? + .with_values(get_platform_value())? .with_function("box", |_, size: usize| Ok(FfiBox::new(size)))? // TODO: discuss about function name. matching with io.open is better? .with_function("dlopen", |_, name: String| { diff --git a/crates/lune-std-ffi/todo.md b/crates/lune-std-ffi/todo.md index 307b29a..9eed077 100644 --- a/crates/lune-std-ffi/todo.md +++ b/crates/lune-std-ffi/todo.md @@ -1,10 +1,9 @@ - use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw}; // pub fn ffi_get_struct_offsets( -// abi: ffi_abi, -// struct_type: *mut ffi_type, -// offsets: *mut usize, +// abi: ffi_abi, +// struct_type: *mut ffi_type, +// offsets: *mut usize, // ) -> ffi_status; - last thing to do @@ -14,10 +13,10 @@ use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw}; # Raw -- [ ] Raw:toRef() -- [ ] Raw:toBox() -- [ ] Raw:intoBox() -- [ ] Raw:intoRef() +- [ ] Raw:toRef() +- [ ] Raw:toBox() +- [ ] Raw:intoBox() +- [ ] Raw:intoRef() # Box @@ -31,6 +30,9 @@ use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw}; # Ref (Unsafe) +- [ ] high, low Boundaries +- [ ] iter + - [x] ref:deref() -> ref - [x] ref:offset(bytes) -> ref - [x] ref:ref() -> ref @@ -70,12 +72,11 @@ from(box|ref|raw, offset) is better idea i think. - [ ] :sub ## subtype + - [x] :ptr() -> Ptr - [~] :arr(len) -> Arr - [x] .size - - # Ptr - [x] .inner @@ -92,6 +93,7 @@ from(box|ref|raw, offset) is better idea i think. Zero sized type. ## Fn + Prototype type of some function. converts lua function into native function pointer or native function pointer into lua function. `ffi.fn({ type }, type) -> fn`