mirror of
https://github.com/lune-org/lune.git
synced 2025-04-08 04:20:54 +01:00
Improve ctype export and Refactor (#243)
This commit is contained in:
parent
6f131e9512
commit
26706d9355
14 changed files with 308 additions and 254 deletions
|
@ -21,7 +21,7 @@ use crate::ffi::ffi_association::{get_association, set_association};
|
|||
// 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.
|
||||
|
||||
pub struct CArr {
|
||||
libffi_type: Type,
|
||||
element_type: Type,
|
||||
struct_type: Type,
|
||||
length: usize,
|
||||
field_size: usize,
|
||||
|
@ -29,12 +29,12 @@ pub struct CArr {
|
|||
}
|
||||
|
||||
impl CArr {
|
||||
pub fn new(libffi_type: Type, length: usize) -> LuaResult<Self> {
|
||||
let struct_type = Type::structure(vec![libffi_type.clone(); length]);
|
||||
let field_size = get_ensured_size(libffi_type.as_raw_ptr())?;
|
||||
pub fn new(element_type: Type, length: usize) -> LuaResult<Self> {
|
||||
let struct_type = Type::structure(vec![element_type.clone(); length]);
|
||||
let field_size = get_ensured_size(element_type.as_raw_ptr())?;
|
||||
|
||||
Ok(Self {
|
||||
libffi_type,
|
||||
element_type,
|
||||
struct_type,
|
||||
length,
|
||||
field_size,
|
||||
|
@ -50,14 +50,18 @@ impl CArr {
|
|||
let fields = type_from_userdata(luatype)?;
|
||||
let carr = lua.create_userdata(Self::new(fields, length)?)?;
|
||||
|
||||
set_association(lua, CARR_INNER, carr.clone(), luatype)?;
|
||||
set_association(lua, CARR_INNER, &carr, luatype)?;
|
||||
Ok(carr)
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> Type {
|
||||
self.libffi_type.clone()
|
||||
self.struct_type.clone()
|
||||
}
|
||||
|
||||
// pub fn get_element_type(&self) -> Type {
|
||||
// self.element_type.clone()
|
||||
// }
|
||||
|
||||
// Stringify cstruct for pretty printing something like:
|
||||
// <CStruct( u8, i32, size = 8 )>
|
||||
pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use libffi::middle::Type;
|
||||
use mlua::prelude::*;
|
||||
|
||||
|
@ -21,7 +19,7 @@ impl CPtr {
|
|||
) -> LuaResult<LuaValue<'lua>> {
|
||||
let value = Self().into_lua(lua)?;
|
||||
|
||||
set_association(lua, CPTR_INNER, value.borrow(), inner)?;
|
||||
set_association(lua, CPTR_INNER, &value, inner)?;
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::cargo_common_metadata)]
|
||||
|
||||
use std::vec::Vec;
|
||||
use std::{borrow::Borrow, vec::Vec};
|
||||
|
||||
use libffi::{
|
||||
low,
|
||||
|
@ -18,17 +18,17 @@ use crate::ffi::ffi_association::{get_association, set_association};
|
|||
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
|
||||
|
||||
pub struct CStruct {
|
||||
libffi_cif: Cif,
|
||||
libffi_type: Type,
|
||||
// libffi_cif: Cif,
|
||||
fields: Vec<Type>,
|
||||
libffi_type: Type,
|
||||
offsets: Vec<usize>,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl CStruct {
|
||||
pub fn new(fields: Vec<Type>) -> LuaResult<Self> {
|
||||
let libffi_type = Type::structure(fields.clone());
|
||||
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
||||
let libffi_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
|
||||
let mut offsets = Vec::<usize>::with_capacity(fields.len());
|
||||
|
@ -52,9 +52,9 @@ impl CStruct {
|
|||
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
|
||||
|
||||
Ok(Self {
|
||||
libffi_cif: libffi_cfi,
|
||||
libffi_type,
|
||||
// libffi_cif: libffi_cfi,
|
||||
fields,
|
||||
libffi_type,
|
||||
offsets,
|
||||
size,
|
||||
})
|
||||
|
@ -69,7 +69,7 @@ impl CStruct {
|
|||
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)?;
|
||||
set_association(lua, CSTRUCT_INNER, &cstruct, table)?;
|
||||
Ok(cstruct)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +1,38 @@
|
|||
#![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 libffi::middle::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,
|
||||
// for ffi_ptrarray_to_raw?
|
||||
// libffi_cif: Cif,
|
||||
libffi_type: Type,
|
||||
size: usize,
|
||||
name: Option<String>,
|
||||
|
||||
// Write converted data from luavalue into some ptr
|
||||
pub luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>,
|
||||
pub luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>,
|
||||
|
||||
// Read luavalue from some ptr
|
||||
pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult<LuaValue>,
|
||||
pub ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>,
|
||||
}
|
||||
|
||||
impl CType {
|
||||
pub fn new(
|
||||
libffi_type: Type,
|
||||
name: Option<String>,
|
||||
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>,
|
||||
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult<LuaValue>,
|
||||
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>,
|
||||
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>,
|
||||
) -> LuaResult<Self> {
|
||||
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
||||
// 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_cif: libffi_cfi,
|
||||
libffi_type,
|
||||
size,
|
||||
name,
|
||||
|
@ -117,122 +111,3 @@ impl LuaUserData for CType {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// export all default c-types
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaValue)>> {
|
||||
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::<c_int>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut c_void| {
|
||||
let value = unsafe { (*ptr.cast::<c_int>()).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::<c_long>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut c_void| {
|
||||
let value = unsafe { (*ptr.cast::<c_long>()).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::<c_longlong>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut c_void| {
|
||||
let value = unsafe { (*ptr.cast::<c_longlong>()).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::<c_char>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut c_void| {
|
||||
let value = unsafe { (*ptr.cast::<c_char>()).into_lua(lua)? };
|
||||
Ok(value)
|
||||
},
|
||||
)?
|
||||
.into_lua(lua)?,
|
||||
),
|
||||
])
|
||||
}
|
||||
|
|
|
@ -12,3 +12,133 @@ 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<Vec<(&'static str, LuaValue)>> {
|
||||
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::<c_int>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut ()| {
|
||||
let value = unsafe { (*ptr.cast::<c_int>()).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::<c_long>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut ()| {
|
||||
let value = unsafe { (*ptr.cast::<c_long>()).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::<c_longlong>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut ()| {
|
||||
let value = unsafe { (*ptr.cast::<c_longlong>()).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::<c_char>()) = value;
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|lua: &Lua, ptr: *mut ()| {
|
||||
let value = unsafe { (*ptr.cast::<c_char>()).into_lua(lua)? };
|
||||
Ok(value)
|
||||
},
|
||||
)?
|
||||
.into_lua(lua)?,
|
||||
),
|
||||
])
|
||||
}
|
||||
|
|
67
crates/lune-std-ffi/src/ffi/ffi_bounds.rs
Normal file
67
crates/lune-std-ffi/src/ffi/ffi_bounds.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Memory range for ref or box data. For boundary checking
|
||||
pub struct FfiRefBounds {
|
||||
// Indicates how much data is above the pointer
|
||||
pub(crate) high: usize,
|
||||
// Indicates how much data is below the pointer
|
||||
pub(crate) low: usize,
|
||||
}
|
||||
|
||||
impl FfiRefBounds {
|
||||
pub fn new(high: usize, low: usize) -> Self {
|
||||
Self { high, low }
|
||||
}
|
||||
|
||||
// Check boundary
|
||||
pub fn check(&self, offset: isize) -> bool {
|
||||
let sign = offset.signum();
|
||||
let offset_abs = offset.unsigned_abs();
|
||||
if sign == -1 {
|
||||
self.high >= offset_abs
|
||||
} else if sign == 1 {
|
||||
self.low >= offset_abs
|
||||
} else {
|
||||
// sign == 0
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Check boundary
|
||||
pub fn check_sized(&self, offset: isize, size: usize) -> bool {
|
||||
let end = offset + (size as isize) - 1;
|
||||
let sign = end.signum();
|
||||
let end_abs = end.unsigned_abs();
|
||||
if sign == -1 {
|
||||
self.high >= end_abs
|
||||
} else if sign == 1 {
|
||||
self.low >= end_abs
|
||||
} else {
|
||||
// sign == 0
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate new bounds from bounds and offset
|
||||
// No boundary checking in here
|
||||
pub fn offset(&self, offset: isize) -> Self {
|
||||
let sign = offset.signum();
|
||||
let offset_abs = offset.unsigned_abs();
|
||||
|
||||
let high: usize = if sign == -1 {
|
||||
self.high - offset_abs
|
||||
} else if sign == 1 {
|
||||
self.high + offset_abs
|
||||
} else {
|
||||
self.high
|
||||
};
|
||||
|
||||
let low: usize = if sign == -1 {
|
||||
self.low + offset_abs
|
||||
} else if sign == 1 {
|
||||
self.low - offset_abs
|
||||
} else {
|
||||
self.low
|
||||
};
|
||||
|
||||
Self { high, low }
|
||||
}
|
||||
}
|
|
@ -11,12 +11,11 @@
|
|||
|
||||
use std::boxed::Box;
|
||||
|
||||
use core::ffi::c_void;
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::BOX_REF_INNER;
|
||||
use super::association_names::REF_INNER;
|
||||
use super::ffi_association::set_association;
|
||||
use super::ffi_ref::FfiRange;
|
||||
use super::ffi_bounds::FfiRefBounds;
|
||||
use super::ffi_ref::FfiRef;
|
||||
|
||||
pub struct FfiBox(Box<[u8]>);
|
||||
|
@ -36,29 +35,10 @@ impl FfiBox {
|
|||
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
|
||||
}
|
||||
|
||||
// Todo: if too big, print as another format
|
||||
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 {
|
||||
|
@ -75,42 +55,51 @@ impl FfiBox {
|
|||
buff
|
||||
}
|
||||
|
||||
// bad naming. i have no idea what should i use
|
||||
// Make FfiRef from box, with boundary checking
|
||||
pub fn luaref<'lua>(
|
||||
lua: &'lua Lua,
|
||||
this: LuaAnyUserData<'lua>,
|
||||
offset: Option<isize>,
|
||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||
let target = this.borrow::<FfiBox>()?;
|
||||
let ptr = if let Some(t) = offset {
|
||||
if t < 0 || t >= (target.size() as isize) {
|
||||
let mut target = this.borrow_mut::<FfiBox>()?;
|
||||
let mut bounds = FfiRefBounds::new(0, target.size());
|
||||
let mut ptr = target.get_ptr();
|
||||
|
||||
// Calculate offset
|
||||
if let Some(t) = offset {
|
||||
if !bounds.check(t) {
|
||||
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()
|
||||
};
|
||||
ptr = unsafe { target.get_ptr().offset(t) };
|
||||
bounds = bounds.offset(t);
|
||||
}
|
||||
|
||||
let luaref = lua.create_userdata(FfiRef::new(
|
||||
ptr,
|
||||
Some(FfiRange {
|
||||
low: 0,
|
||||
high: target.size() as isize,
|
||||
}),
|
||||
))?;
|
||||
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), Some(bounds)))?;
|
||||
|
||||
set_association(lua, BOX_REF_INNER, luaref.clone(), this.clone())?;
|
||||
// Makes box alive longer then ref
|
||||
set_association(lua, REF_INNER, &luaref, &this)?;
|
||||
|
||||
Ok(luaref)
|
||||
}
|
||||
|
||||
// Fill every field with 0
|
||||
pub fn zero(&mut self) {
|
||||
self.0.fill(0u8);
|
||||
}
|
||||
|
||||
// Get size of box
|
||||
pub fn size(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
// Get raw ptr
|
||||
pub fn get_ptr(&mut self) -> *mut u8 {
|
||||
self.0.as_mut_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for FfiBox {
|
||||
|
@ -119,6 +108,7 @@ impl LuaUserData for FfiBox {
|
|||
}
|
||||
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
// For convenience, :zero returns self.
|
||||
methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
|
||||
this.borrow_mut::<FfiBox>()?.zero();
|
||||
Ok(this)
|
||||
|
@ -130,8 +120,6 @@ impl LuaUserData for FfiBox {
|
|||
Ok(luaref)
|
||||
},
|
||||
);
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
||||
Ok(this.binary_print())
|
||||
});
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(this.stringify()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::ffi::c_void;
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::ffi_box::FfiBox;
|
||||
|
@ -13,12 +11,14 @@ pub const FFI_STATUS_NAMES: [&str; 4] = [
|
|||
"ffi_status_FFI_BAD_ARGTYPE",
|
||||
];
|
||||
|
||||
// Get raw pointer from userdata
|
||||
// TODO: boundary check
|
||||
pub unsafe fn get_ptr_from_userdata(
|
||||
userdata: &LuaAnyUserData,
|
||||
offset: Option<isize>,
|
||||
) -> LuaResult<*mut c_void> {
|
||||
) -> LuaResult<*mut ()> {
|
||||
let ptr = if userdata.is::<FfiBox>() {
|
||||
userdata.borrow::<FfiBox>()?.get_ptr()
|
||||
userdata.borrow_mut::<FfiBox>()?.get_ptr().cast()
|
||||
} else if userdata.is::<FfiRef>() {
|
||||
userdata.borrow::<FfiRef>()?.get_ptr()
|
||||
} else {
|
||||
|
@ -26,7 +26,7 @@ pub unsafe fn get_ptr_from_userdata(
|
|||
};
|
||||
|
||||
let ptr = if let Some(t) = offset {
|
||||
ptr.offset(t)
|
||||
ptr.cast::<u8>().offset(t).cast()
|
||||
} else {
|
||||
ptr
|
||||
};
|
||||
|
|
|
@ -39,9 +39,9 @@ impl FfiLib {
|
|||
.map_err(|err| LuaError::external(format!("{err}")))?
|
||||
};
|
||||
|
||||
let luasym = lua.create_userdata(FfiRef::new(*sym, None))?;
|
||||
let luasym = lua.create_userdata(FfiRef::new((*sym).cast(), None))?;
|
||||
|
||||
set_association(lua, SYM_INNER, luasym.clone(), this.clone())?;
|
||||
set_association(lua, SYM_INNER, &luasym, &this)?;
|
||||
|
||||
Ok(luasym)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use core::ffi::c_void;
|
||||
use std::{convert, mem::transmute, ptr};
|
||||
// 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.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use core::ffi::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::REF_INNER;
|
||||
use super::ffi_association::set_association;
|
||||
use super::ffi_association::{get_association, set_association};
|
||||
use super::ffi_bounds::FfiRefBounds;
|
||||
|
||||
// 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
|
||||
|
@ -12,22 +12,17 @@ use super::ffi_association::set_association;
|
|||
// 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<FfiRange>,
|
||||
ptr: *mut (),
|
||||
range: Option<FfiRefBounds>,
|
||||
}
|
||||
|
||||
impl FfiRef {
|
||||
pub fn new(ptr: *mut c_void, range: Option<FfiRange>) -> Self {
|
||||
pub fn new(ptr: *mut (), range: Option<FfiRefBounds>) -> Self {
|
||||
Self { ptr, range }
|
||||
}
|
||||
|
||||
// bad naming. i have no idea what should i use
|
||||
// Make FfiRef from ref
|
||||
pub fn luaref<'lua>(
|
||||
lua: &'lua Lua,
|
||||
this: LuaAnyUserData<'lua>,
|
||||
|
@ -35,52 +30,59 @@ impl FfiRef {
|
|||
let target = this.borrow::<FfiRef>()?;
|
||||
|
||||
let luaref = lua.create_userdata(FfiRef::new(
|
||||
ptr::from_ref(&target.ptr) as *mut c_void,
|
||||
Some(FfiRange {
|
||||
ptr::from_ref(&target.ptr) as *mut (),
|
||||
Some(FfiRefBounds {
|
||||
low: 0,
|
||||
high: size_of::<usize>() as isize,
|
||||
high: size_of::<usize>(),
|
||||
}),
|
||||
))?;
|
||||
|
||||
set_association(lua, REF_INNER, luaref.clone(), this.clone())?;
|
||||
// If the ref holds a box, make sure the new ref also holds the box
|
||||
if let Some(t) = get_association(lua, REF_INNER, &this)? {
|
||||
set_association(lua, REF_INNER, &luaref, t)?;
|
||||
}
|
||||
|
||||
Ok(luaref)
|
||||
}
|
||||
|
||||
pub fn get_ptr(&self) -> *mut c_void {
|
||||
pub fn get_ptr(&self) -> *mut () {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
pub unsafe fn deref(&self) -> Self {
|
||||
Self::new(*self.ptr.cast::<*mut c_void>(), None)
|
||||
Self::new(*self.ptr.cast::<*mut ()>(), None)
|
||||
}
|
||||
|
||||
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
||||
let range = if let Some(ref t) = self.range {
|
||||
let high = t.high - offset;
|
||||
let low = t.low - offset;
|
||||
|
||||
if low > 0 || high < 0 {
|
||||
if let Some(ref t) = self.range {
|
||||
if !t.check(offset) {
|
||||
return Err(LuaError::external(format!(
|
||||
"Offset is out of bounds. low: {}, high: {}. offset got {}",
|
||||
t.low, t.high, offset
|
||||
"Offset is out of bounds. high: {}, low: {}. offset got {}",
|
||||
t.high, t.low, offset
|
||||
)));
|
||||
}
|
||||
}
|
||||
let range = self.range.as_ref().map(|t| t.offset(offset));
|
||||
|
||||
Some(FfiRange { high, low })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Self::new(self.ptr.offset(offset), range))
|
||||
Ok(Self::new(
|
||||
self.ptr.cast::<u8>().offset(offset).cast(),
|
||||
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_function("deref", |lua, this: LuaAnyUserData| {
|
||||
let inner = get_association(lua, REF_INNER, &this)?;
|
||||
let ffiref = this.borrow::<FfiRef>()?;
|
||||
let result = lua.create_userdata(unsafe { ffiref.deref() })?;
|
||||
|
||||
if let Some(t) = inner {
|
||||
set_association(lua, REF_INNER, &result, &t)?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
});
|
||||
methods.add_method("offset", |_, this, offset: isize| {
|
||||
let ffiref = unsafe { this.offset(offset)? };
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub(super) mod ffi_association;
|
||||
pub(super) mod ffi_bounds;
|
||||
pub(super) mod ffi_box;
|
||||
pub(super) mod ffi_helper;
|
||||
pub(super) mod ffi_lib;
|
||||
|
@ -8,6 +9,5 @@ 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";
|
||||
}
|
||||
|
|
|
@ -6,13 +6,10 @@ use mlua::prelude::*;
|
|||
mod c;
|
||||
mod ffi;
|
||||
|
||||
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;
|
||||
use crate::c::{c_fn::CFn, c_struct::CStruct, create_all_types};
|
||||
use crate::ffi::{
|
||||
ffi_association::get_table, ffi_box::FfiBox, ffi_lib::FfiLib, ffi_platform::get_platform_value,
|
||||
};
|
||||
|
||||
/**
|
||||
Creates the `ffi` standard library module.
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
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,
|
||||
// ) -> ffi_status;
|
||||
|
||||
- last thing to do
|
||||
- [ ] Add tests
|
||||
- [ ] Add docs
|
||||
|
@ -23,8 +15,9 @@ use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw};
|
|||
- [x] ffi.box(size)
|
||||
- [x] .size
|
||||
- [x] :zero()
|
||||
- [?] :ref(offset?=0) => ref
|
||||
- offset is not impled
|
||||
- [x] :ref(offset?=0) => ref
|
||||
- [x] tostring
|
||||
|
||||
- [~] :copy(box,size?=-1,offset?=0)
|
||||
- working on it
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue