Skip to content

Commit

Permalink
Update readRef method to allow reuse RefData (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
qwreey committed Nov 12, 2024
1 parent 461ab26 commit 627c2c9
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 86 deletions.
2 changes: 1 addition & 1 deletion crates/lune-std-ffi/src/c/arr_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use mlua::prelude::*;
use super::{association_names::CARR_INNER, helper, method_provider};
use crate::ffi::{association, libffi_helper::get_ensured_size, FfiConvert, FfiData, FfiSize};

// This is a series of some type.
// Series of some type.
// It provides the final size and the offset of the index,
// but does not allow multidimensional arrays because of API complexity.
// Multidimensional arrays can be implemented
Expand Down
23 changes: 3 additions & 20 deletions crates/lune-std-ffi/src/c/fn_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,7 @@ use crate::{
},
};

// cfn is a type declaration for a function.
// Basically, when calling an external function, this type declaration
// is referred to and type conversion is automatically assisted.

// However, in order to save on type conversion costs,
// users keep values ​​they will use continuously in a box and use them multiple times.
// Alternatively, if the types are the same,you can save the cost of creating
// a new space by directly passing FfiRaw,
// the result value of another function or the argument value of the callback.

// Defining cfn simply lists the function's actual argument positions and conversions.
// You must decide how to process the data in Lua.

// The name cfn is intentional. This is because any *c_void is
// moved to a Lua function or vice versa.

// Function pointer type
pub struct CFnInfo {
cif: Cif,
arg_info_list: Vec<FfiArg>,
Expand Down Expand Up @@ -147,6 +132,7 @@ impl CFnInfo {
}
}

// Create ClosureData with lua function
pub fn create_closure<'lua>(
&self,
lua: &'lua Lua,
Expand All @@ -167,6 +153,7 @@ impl CFnInfo {
Ok(closure_data)
}

// Create CallableData from RefData
pub fn create_callable<'lua>(
&self,
lua: &'lua Lua,
Expand Down Expand Up @@ -209,10 +196,6 @@ impl LuaUserData for CFnInfo {
fields.add_field_method_get("size", |_lua, _this| Ok(SIZE_OF_POINTER));
}
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// Subtype
method_provider::provide_ptr(methods);
method_provider::provide_arr(methods);

// ToString
method_provider::provide_to_string(methods);

Expand Down
77 changes: 56 additions & 21 deletions crates/lune-std-ffi/src/c/ptr_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use mlua::prelude::*;

use super::{association_names::CPTR_INNER, ctype_helper, helper, method_provider};
use crate::{
data::{GetFfiData, RefBounds, RefData, RefFlag},
data::{GetFfiData, RefData, RefFlag, UNSIZED_BOUNDS},
ffi::{
association, libffi_helper::SIZE_OF_POINTER, FfiConvert, FfiData, FfiSignedness, FfiSize,
},
Expand All @@ -16,7 +16,6 @@ const READ_REF_FLAGS: u8 =
RefFlag::Offsetable.value() | RefFlag::Readable.value() | RefFlag::Writable.value();

pub struct CPtrInfo {
inner_size: usize,
inner_is_cptr: bool,
}

Expand All @@ -33,45 +32,51 @@ impl FfiSize for CPtrInfo {
}

impl FfiConvert for CPtrInfo {
// Convert luavalue into data, then write into ptr
// Write address of RefData
unsafe fn value_into_data<'lua>(
&self,
_lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn FfiData>,
value: LuaValue<'lua>,
) -> LuaResult<()> {
let value_userdata = value.as_userdata().ok_or_else(|| {
LuaError::external(format!(
let LuaValue::UserData(value_userdata) = value else {
return Err(LuaError::external(format!(
"Value must be a RefData, BoxData or ClosureData, got {}",
value.type_name()
))
})?;
)));
};
*data_handle
.get_inner_pointer()
.byte_offset(offset)
.cast::<*mut ()>() = value_userdata.get_ffi_data()?.get_inner_pointer();
Ok(())
}

// Read data from ptr, then convert into luavalue
// Read address, create RefData
unsafe fn value_from_data<'lua>(
&self,
lua: &'lua Lua,
offset: isize,
data_handle: &Ref<dyn FfiData>,
) -> LuaResult<LuaValue<'lua>> {
Ok(LuaValue::UserData(lua.create_userdata(RefData::new(
unsafe { data_handle.get_inner_pointer().byte_offset(offset) },
if self.inner_is_cptr {
READ_CPTR_REF_FLAGS
} else {
READ_REF_FLAGS
},
RefBounds::new(0, self.inner_size),
))?))
Ok(LuaValue::UserData(
lua.create_userdata(RefData::new(
*data_handle
.get_inner_pointer()
.byte_offset(offset)
.cast::<*mut ()>(),
if self.inner_is_cptr {
READ_CPTR_REF_FLAGS
} else {
READ_REF_FLAGS
},
UNSIZED_BOUNDS,
))?,
))
}

// Copy Address
unsafe fn copy_data(
&self,
_lua: &Lua,
Expand All @@ -82,7 +87,10 @@ impl FfiConvert for CPtrInfo {
) -> LuaResult<()> {
*dst.get_inner_pointer()
.byte_offset(dst_offset)
.cast::<*mut ()>() = src.get_inner_pointer().byte_offset(src_offset);
.cast::<*mut ()>() = *src
.get_inner_pointer()
.byte_offset(src_offset)
.cast::<*mut ()>();
Ok(())
}
}
Expand All @@ -95,7 +103,6 @@ impl CPtrInfo {
inner: &LuaAnyUserData,
) -> LuaResult<LuaAnyUserData<'lua>> {
let value = lua.create_userdata(Self {
inner_size: helper::get_size(inner)?,
inner_is_cptr: inner.is::<CPtrInfo>(),
})?;

Expand Down Expand Up @@ -143,8 +150,36 @@ impl LuaUserData for CPtrInfo {

methods.add_method(
"readRef",
|lua, this, (target, offset): (LuaAnyUserData, Option<isize>)| unsafe {
this.value_from_data(lua, offset.unwrap_or(0), &target.get_ffi_data()?)
|lua,
this,
(target, offset, ref_data): (
LuaAnyUserData,
Option<isize>,
Option<LuaAnyUserData>,
)| unsafe {
if let Some(ref_userdata) = ref_data {
if !ref_userdata.is::<RefData>() {
return Err(LuaError::external(""));
}
RefData::update(
lua,
ref_userdata.clone(),
*target
.get_ffi_data()?
.get_inner_pointer()
.byte_offset(offset.unwrap_or(0))
.cast::<*mut ()>(),
if this.inner_is_cptr {
READ_CPTR_REF_FLAGS
} else {
READ_REF_FLAGS
},
UNSIZED_BOUNDS,
)?;
Ok(LuaValue::UserData(ref_userdata))
} else {
this.value_from_data(lua, offset.unwrap_or(0), &target.get_ffi_data()?)
}
},
);
methods.add_method(
Expand Down
2 changes: 1 addition & 1 deletion crates/lune-std-ffi/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use self::{
callable_data::CallableData,
closure_data::ClosureData,
lib_data::LibData,
ref_data::{create_nullref, RefBounds, RefData, RefFlag},
ref_data::{create_nullref, RefBounds, RefData, RefFlag, UNSIZED_BOUNDS},
};
use crate::ffi::FfiData;

Expand Down
17 changes: 17 additions & 0 deletions crates/lune-std-ffi/src/data/ref_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ impl RefData {
}
}

pub fn update<'lua>(
lua: &'lua Lua,
this: LuaAnyUserData<'lua>,
ptr: *mut (),
flags: u8,
boundary: RefBounds,
) -> LuaResult<()> {
let mut target = this.borrow_mut::<RefData>()?;
association::set(lua, REF_INNER, &this, LuaNil)?;

**target.ptr = ptr;
target.flags = flags;
target.boundary = boundary;

Ok(())
}

// Create reference of this reference
pub fn luaref<'lua>(
lua: &'lua Lua,
Expand Down
Loading

0 comments on commit 627c2c9

Please sign in to comment.