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.
|
// 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 {
|
pub struct CArr {
|
||||||
libffi_type: Type,
|
element_type: Type,
|
||||||
struct_type: Type,
|
struct_type: Type,
|
||||||
length: usize,
|
length: usize,
|
||||||
field_size: usize,
|
field_size: usize,
|
||||||
|
@ -29,12 +29,12 @@ pub struct CArr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CArr {
|
impl CArr {
|
||||||
pub fn new(libffi_type: Type, length: usize) -> LuaResult<Self> {
|
pub fn new(element_type: Type, length: usize) -> LuaResult<Self> {
|
||||||
let struct_type = Type::structure(vec![libffi_type.clone(); length]);
|
let struct_type = Type::structure(vec![element_type.clone(); length]);
|
||||||
let field_size = get_ensured_size(libffi_type.as_raw_ptr())?;
|
let field_size = get_ensured_size(element_type.as_raw_ptr())?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
libffi_type,
|
element_type,
|
||||||
struct_type,
|
struct_type,
|
||||||
length,
|
length,
|
||||||
field_size,
|
field_size,
|
||||||
|
@ -50,14 +50,18 @@ impl CArr {
|
||||||
let fields = type_from_userdata(luatype)?;
|
let fields = type_from_userdata(luatype)?;
|
||||||
let carr = lua.create_userdata(Self::new(fields, length)?)?;
|
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)
|
Ok(carr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type(&self) -> Type {
|
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:
|
// Stringify cstruct for pretty printing something like:
|
||||||
// <CStruct( u8, i32, size = 8 )>
|
// <CStruct( u8, i32, size = 8 )>
|
||||||
pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
|
pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
@ -21,7 +19,7 @@ impl CPtr {
|
||||||
) -> LuaResult<LuaValue<'lua>> {
|
) -> LuaResult<LuaValue<'lua>> {
|
||||||
let value = Self().into_lua(lua)?;
|
let value = Self().into_lua(lua)?;
|
||||||
|
|
||||||
set_association(lua, CPTR_INNER, value.borrow(), inner)?;
|
set_association(lua, CPTR_INNER, &value, inner)?;
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use std::vec::Vec;
|
use std::{borrow::Borrow, vec::Vec};
|
||||||
|
|
||||||
use libffi::{
|
use libffi::{
|
||||||
low,
|
low,
|
||||||
|
@ -18,17 +18,17 @@ use crate::ffi::ffi_association::{get_association, set_association};
|
||||||
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
|
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
|
||||||
|
|
||||||
pub struct CStruct {
|
pub struct CStruct {
|
||||||
libffi_cif: Cif,
|
// libffi_cif: Cif,
|
||||||
libffi_type: Type,
|
|
||||||
fields: Vec<Type>,
|
fields: Vec<Type>,
|
||||||
|
libffi_type: Type,
|
||||||
offsets: Vec<usize>,
|
offsets: Vec<usize>,
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CStruct {
|
impl CStruct {
|
||||||
pub fn new(fields: Vec<Type>) -> LuaResult<Self> {
|
pub fn new(fields: Vec<Type>) -> LuaResult<Self> {
|
||||||
let libffi_type = Type::structure(fields.clone());
|
let libffi_type = Type::structure(fields.iter().cloned());
|
||||||
let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
// let libffi_cfi = Cif::new(vec![libffi_type.clone()], Type::void());
|
||||||
|
|
||||||
// Get field offsets with ffi_get_struct_offsets
|
// Get field offsets with ffi_get_struct_offsets
|
||||||
let mut offsets = Vec::<usize>::with_capacity(fields.len());
|
let mut offsets = Vec::<usize>::with_capacity(fields.len());
|
||||||
|
@ -52,9 +52,9 @@ impl CStruct {
|
||||||
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
|
let size = unsafe { (*libffi_type.as_raw_ptr()).size };
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
libffi_cif: libffi_cfi,
|
// libffi_cif: libffi_cfi,
|
||||||
libffi_type,
|
|
||||||
fields,
|
fields,
|
||||||
|
libffi_type,
|
||||||
offsets,
|
offsets,
|
||||||
size,
|
size,
|
||||||
})
|
})
|
||||||
|
@ -69,7 +69,7 @@ impl CStruct {
|
||||||
let fields = type_list_from_table(&table)?;
|
let fields = type_list_from_table(&table)?;
|
||||||
let cstruct = lua.create_userdata(Self::new(fields)?)?;
|
let cstruct = lua.create_userdata(Self::new(fields)?)?;
|
||||||
table.set_readonly(true);
|
table.set_readonly(true);
|
||||||
set_association(lua, CSTRUCT_INNER, cstruct.clone(), table)?;
|
set_association(lua, CSTRUCT_INNER, &cstruct, table)?;
|
||||||
Ok(cstruct)
|
Ok(cstruct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,38 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use core::ffi::{
|
use libffi::middle::Type;
|
||||||
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 mlua::prelude::*;
|
||||||
|
|
||||||
use super::c_arr::CArr;
|
use super::c_arr::CArr;
|
||||||
use super::c_helper::get_ensured_size;
|
use super::c_helper::get_ensured_size;
|
||||||
use super::c_ptr::CPtr;
|
use super::c_ptr::CPtr;
|
||||||
use crate::ffi::ffi_helper::get_ptr_from_userdata;
|
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 {
|
pub struct CType {
|
||||||
libffi_cif: Cif,
|
// for ffi_ptrarray_to_raw?
|
||||||
|
// libffi_cif: Cif,
|
||||||
libffi_type: Type,
|
libffi_type: Type,
|
||||||
size: usize,
|
size: usize,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
|
||||||
// Write converted data from luavalue into some ptr
|
// 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
|
// 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 {
|
impl CType {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
libffi_type: Type,
|
libffi_type: Type,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut c_void) -> LuaResult<()>,
|
luavalue_into_ptr: fn(value: LuaValue, ptr: *mut ()) -> LuaResult<()>,
|
||||||
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut c_void) -> LuaResult<LuaValue>,
|
ptr_into_luavalue: fn(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue>,
|
||||||
) -> LuaResult<Self> {
|
) -> 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())?;
|
let size = get_ensured_size(libffi_type.as_raw_ptr())?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
libffi_cif: libffi_cfi,
|
// libffi_cif: libffi_cfi,
|
||||||
libffi_type,
|
libffi_type,
|
||||||
size,
|
size,
|
||||||
name,
|
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 CARR_INNER: &str = "__carr_inner";
|
||||||
pub const CSTRUCT_INNER: &str = "__cstruct_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 std::boxed::Box;
|
||||||
|
|
||||||
use core::ffi::c_void;
|
|
||||||
use mlua::prelude::*;
|
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_association::set_association;
|
||||||
use super::ffi_ref::FfiRange;
|
use super::ffi_bounds::FfiRefBounds;
|
||||||
use super::ffi_ref::FfiRef;
|
use super::ffi_ref::FfiRef;
|
||||||
|
|
||||||
pub struct FfiBox(Box<[u8]>);
|
pub struct FfiBox(Box<[u8]>);
|
||||||
|
@ -36,29 +35,10 @@ impl FfiBox {
|
||||||
Self(vec_heap.into_boxed_slice())
|
Self(vec_heap.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
|
||||||
self.0.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn copy(&self, target: &mut FfiBox) {}
|
// pub fn copy(&self, target: &mut FfiBox) {}
|
||||||
|
|
||||||
pub fn get_ptr(&self) -> *mut c_void {
|
// Todo: if too big, print as another format
|
||||||
self.0.as_ptr() as *mut c_void
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn stringify(&self) -> String {
|
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);
|
let mut buff: String = String::with_capacity(self.size() * 10 - 2);
|
||||||
for (pos, value) in self.0.iter().enumerate() {
|
for (pos, value) in self.0.iter().enumerate() {
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
|
@ -75,42 +55,51 @@ impl FfiBox {
|
||||||
buff
|
buff
|
||||||
}
|
}
|
||||||
|
|
||||||
// bad naming. i have no idea what should i use
|
// Make FfiRef from box, with boundary checking
|
||||||
pub fn luaref<'lua>(
|
pub fn luaref<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
this: LuaAnyUserData<'lua>,
|
this: LuaAnyUserData<'lua>,
|
||||||
offset: Option<isize>,
|
offset: Option<isize>,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
let target = this.borrow::<FfiBox>()?;
|
let mut target = this.borrow_mut::<FfiBox>()?;
|
||||||
let ptr = if let Some(t) = offset {
|
let mut bounds = FfiRefBounds::new(0, target.size());
|
||||||
if t < 0 || t >= (target.size() as isize) {
|
let mut ptr = target.get_ptr();
|
||||||
|
|
||||||
|
// Calculate offset
|
||||||
|
if let Some(t) = offset {
|
||||||
|
if !bounds.check(t) {
|
||||||
return Err(LuaError::external(format!(
|
return Err(LuaError::external(format!(
|
||||||
"Offset is out of bounds. box.size: {}. offset got {}",
|
"Offset is out of bounds. box.size: {}. offset got {}",
|
||||||
target.size(),
|
target.size(),
|
||||||
t
|
t
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
unsafe { target.get_ptr().offset(t) }
|
ptr = unsafe { target.get_ptr().offset(t) };
|
||||||
} else {
|
bounds = bounds.offset(t);
|
||||||
target.get_ptr()
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let luaref = lua.create_userdata(FfiRef::new(
|
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), Some(bounds)))?;
|
||||||
ptr,
|
|
||||||
Some(FfiRange {
|
|
||||||
low: 0,
|
|
||||||
high: target.size() as isize,
|
|
||||||
}),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
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)
|
Ok(luaref)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill every field with 0
|
||||||
pub fn zero(&mut self) {
|
pub fn zero(&mut self) {
|
||||||
self.0.fill(0u8);
|
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 {
|
impl LuaUserData for FfiBox {
|
||||||
|
@ -119,6 +108,7 @@ impl LuaUserData for FfiBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
// For convenience, :zero returns self.
|
||||||
methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
|
methods.add_function_mut("zero", |_, this: LuaAnyUserData| {
|
||||||
this.borrow_mut::<FfiBox>()?.zero();
|
this.borrow_mut::<FfiBox>()?.zero();
|
||||||
Ok(this)
|
Ok(this)
|
||||||
|
@ -130,8 +120,6 @@ impl LuaUserData for FfiBox {
|
||||||
Ok(luaref)
|
Ok(luaref)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(this.stringify()));
|
||||||
Ok(this.binary_print())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::ffi::c_void;
|
|
||||||
|
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
use super::ffi_box::FfiBox;
|
use super::ffi_box::FfiBox;
|
||||||
|
@ -13,12 +11,14 @@ pub const FFI_STATUS_NAMES: [&str; 4] = [
|
||||||
"ffi_status_FFI_BAD_ARGTYPE",
|
"ffi_status_FFI_BAD_ARGTYPE",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Get raw pointer from userdata
|
||||||
|
// TODO: boundary check
|
||||||
pub unsafe fn get_ptr_from_userdata(
|
pub unsafe fn get_ptr_from_userdata(
|
||||||
userdata: &LuaAnyUserData,
|
userdata: &LuaAnyUserData,
|
||||||
offset: Option<isize>,
|
offset: Option<isize>,
|
||||||
) -> LuaResult<*mut c_void> {
|
) -> LuaResult<*mut ()> {
|
||||||
let ptr = if userdata.is::<FfiBox>() {
|
let ptr = if userdata.is::<FfiBox>() {
|
||||||
userdata.borrow::<FfiBox>()?.get_ptr()
|
userdata.borrow_mut::<FfiBox>()?.get_ptr().cast()
|
||||||
} else if userdata.is::<FfiRef>() {
|
} else if userdata.is::<FfiRef>() {
|
||||||
userdata.borrow::<FfiRef>()?.get_ptr()
|
userdata.borrow::<FfiRef>()?.get_ptr()
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,7 +26,7 @@ pub unsafe fn get_ptr_from_userdata(
|
||||||
};
|
};
|
||||||
|
|
||||||
let ptr = if let Some(t) = offset {
|
let ptr = if let Some(t) = offset {
|
||||||
ptr.offset(t)
|
ptr.cast::<u8>().offset(t).cast()
|
||||||
} else {
|
} else {
|
||||||
ptr
|
ptr
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,9 +39,9 @@ impl FfiLib {
|
||||||
.map_err(|err| LuaError::external(format!("{err}")))?
|
.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)
|
Ok(luasym)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use core::ffi::c_void;
|
// use core::ffi::c_void;
|
||||||
use std::{convert, mem::transmute, ptr};
|
// use std::{convert, mem::transmute, ptr};
|
||||||
|
|
||||||
// This is raw data coming from outside.
|
// This is raw data coming from outside.
|
||||||
// Users must convert it to a Lua value, reference, or box to use it.
|
// 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 std::ptr;
|
||||||
|
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
use super::association_names::REF_INNER;
|
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.
|
// 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
|
// 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,
|
// If it references an area managed by Lua,
|
||||||
// the box will remain as long as this reference is alive.
|
// 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 {
|
pub struct FfiRef {
|
||||||
ptr: *mut c_void,
|
ptr: *mut (),
|
||||||
range: Option<FfiRange>,
|
range: Option<FfiRefBounds>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FfiRef {
|
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 }
|
Self { ptr, range }
|
||||||
}
|
}
|
||||||
|
|
||||||
// bad naming. i have no idea what should i use
|
// Make FfiRef from ref
|
||||||
pub fn luaref<'lua>(
|
pub fn luaref<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
this: LuaAnyUserData<'lua>,
|
this: LuaAnyUserData<'lua>,
|
||||||
|
@ -35,52 +30,59 @@ impl FfiRef {
|
||||||
let target = this.borrow::<FfiRef>()?;
|
let target = this.borrow::<FfiRef>()?;
|
||||||
|
|
||||||
let luaref = lua.create_userdata(FfiRef::new(
|
let luaref = lua.create_userdata(FfiRef::new(
|
||||||
ptr::from_ref(&target.ptr) as *mut c_void,
|
ptr::from_ref(&target.ptr) as *mut (),
|
||||||
Some(FfiRange {
|
Some(FfiRefBounds {
|
||||||
low: 0,
|
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)
|
Ok(luaref)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ptr(&self) -> *mut c_void {
|
pub fn get_ptr(&self) -> *mut () {
|
||||||
self.ptr
|
self.ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn deref(&self) -> Self {
|
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> {
|
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
||||||
let range = if let Some(ref t) = self.range {
|
if let Some(ref t) = self.range {
|
||||||
let high = t.high - offset;
|
if !t.check(offset) {
|
||||||
let low = t.low - offset;
|
|
||||||
|
|
||||||
if low > 0 || high < 0 {
|
|
||||||
return Err(LuaError::external(format!(
|
return Err(LuaError::external(format!(
|
||||||
"Offset is out of bounds. low: {}, high: {}. offset got {}",
|
"Offset is out of bounds. high: {}, low: {}. offset got {}",
|
||||||
t.low, t.high, offset
|
t.high, t.low, offset
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
let range = self.range.as_ref().map(|t| t.offset(offset));
|
||||||
|
|
||||||
Some(FfiRange { high, low })
|
Ok(Self::new(
|
||||||
} else {
|
self.ptr.cast::<u8>().offset(offset).cast(),
|
||||||
None
|
range,
|
||||||
};
|
))
|
||||||
|
|
||||||
Ok(Self::new(self.ptr.offset(offset), range))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaUserData for FfiRef {
|
impl LuaUserData for FfiRef {
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
methods.add_method("deref", |_, this, ()| {
|
methods.add_function("deref", |lua, this: LuaAnyUserData| {
|
||||||
let ffiref = unsafe { this.deref() };
|
let inner = get_association(lua, REF_INNER, &this)?;
|
||||||
Ok(ffiref)
|
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| {
|
methods.add_method("offset", |_, this, offset: isize| {
|
||||||
let ffiref = unsafe { this.offset(offset)? };
|
let ffiref = unsafe { this.offset(offset)? };
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub(super) mod ffi_association;
|
pub(super) mod ffi_association;
|
||||||
|
pub(super) mod ffi_bounds;
|
||||||
pub(super) mod ffi_box;
|
pub(super) mod ffi_box;
|
||||||
pub(super) mod ffi_helper;
|
pub(super) mod ffi_helper;
|
||||||
pub(super) mod ffi_lib;
|
pub(super) mod ffi_lib;
|
||||||
|
@ -8,6 +9,5 @@ pub(super) mod ffi_ref;
|
||||||
|
|
||||||
// Named registry table names
|
// Named registry table names
|
||||||
mod association_names {
|
mod association_names {
|
||||||
pub const BOX_REF_INNER: &str = "__box_ref";
|
|
||||||
pub const REF_INNER: &str = "__ref_inner";
|
pub const REF_INNER: &str = "__ref_inner";
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,10 @@ use mlua::prelude::*;
|
||||||
mod c;
|
mod c;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
|
||||||
use crate::c::c_fn::CFn;
|
use crate::c::{c_fn::CFn, c_struct::CStruct, create_all_types};
|
||||||
use crate::c::c_struct::CStruct;
|
use crate::ffi::{
|
||||||
use crate::c::c_type::create_all_types;
|
ffi_association::get_table, ffi_box::FfiBox, ffi_lib::FfiLib, ffi_platform::get_platform_value,
|
||||||
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.
|
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
|
- last thing to do
|
||||||
- [ ] Add tests
|
- [ ] Add tests
|
||||||
- [ ] Add docs
|
- [ ] Add docs
|
||||||
|
@ -23,8 +15,9 @@ use libffi::raw::{ffi_cif, ffi_ptrarray_to_raw};
|
||||||
- [x] ffi.box(size)
|
- [x] ffi.box(size)
|
||||||
- [x] .size
|
- [x] .size
|
||||||
- [x] :zero()
|
- [x] :zero()
|
||||||
- [?] :ref(offset?=0) => ref
|
- [x] :ref(offset?=0) => ref
|
||||||
- offset is not impled
|
- [x] tostring
|
||||||
|
|
||||||
- [~] :copy(box,size?=-1,offset?=0)
|
- [~] :copy(box,size?=-1,offset?=0)
|
||||||
- working on it
|
- working on it
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue