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