mirror of
https://github.com/lune-org/lune.git
synced 2025-04-04 10:30:54 +01:00
Improve conversion performance by caching dyn handle on subtype (#243)
This commit is contained in:
parent
b54ea519ba
commit
dd6a3861e5
12 changed files with 244 additions and 176 deletions
|
@ -1,10 +1,17 @@
|
|||
use std::cell::Ref;
|
||||
|
||||
use libffi::middle::Type;
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::CARR_INNER;
|
||||
use super::c_helper::{get_ensured_size, libffi_type_from_userdata, pretty_format_userdata};
|
||||
use super::c_ptr::CPtr;
|
||||
use crate::ffi::ffi_association::{get_association, set_association};
|
||||
use super::{
|
||||
association_names::CARR_INNER,
|
||||
c_helper::{get_conv, get_ensured_size, libffi_type_from_userdata, pretty_format_userdata},
|
||||
CPtr,
|
||||
};
|
||||
use crate::ffi::{
|
||||
ffi_association::{get_association, set_association},
|
||||
FfiBox, GetNativeDataHandle, NativeConvert, NativeDataHandle, NativeSignedness, NativeSize,
|
||||
};
|
||||
|
||||
// This is a series of some type.
|
||||
// It provides the final size and the offset of the index,
|
||||
|
@ -18,24 +25,30 @@ 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 {
|
||||
element_type: Type,
|
||||
// element_type: Type,
|
||||
struct_type: Type,
|
||||
length: usize,
|
||||
field_size: usize,
|
||||
size: usize,
|
||||
conv: *const dyn NativeConvert,
|
||||
}
|
||||
|
||||
impl CArr {
|
||||
pub fn new(element_type: Type, length: usize) -> LuaResult<Self> {
|
||||
let struct_type = Type::structure(vec![element_type.clone(); length]);
|
||||
pub fn new(
|
||||
element_type: Type,
|
||||
length: usize,
|
||||
conv: *const dyn NativeConvert,
|
||||
) -> LuaResult<Self> {
|
||||
let field_size = get_ensured_size(element_type.as_raw_ptr())?;
|
||||
let struct_type = Type::structure(vec![element_type.clone(); length]);
|
||||
|
||||
Ok(Self {
|
||||
element_type,
|
||||
// element_type,
|
||||
struct_type,
|
||||
length,
|
||||
field_size,
|
||||
size: field_size * length,
|
||||
conv,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -45,16 +58,13 @@ impl CArr {
|
|||
length: usize,
|
||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||
let fields = libffi_type_from_userdata(lua, luatype)?;
|
||||
let carr = lua.create_userdata(Self::new(fields, length)?)?;
|
||||
let conv = unsafe { get_conv(luatype)? };
|
||||
let carr = lua.create_userdata(Self::new(fields, length, conv)?)?;
|
||||
|
||||
set_association(lua, CARR_INNER, &carr, luatype)?;
|
||||
Ok(carr)
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn get_length(&self) -> usize {
|
||||
self.length
|
||||
}
|
||||
|
@ -63,9 +73,9 @@ impl CArr {
|
|||
&self.struct_type
|
||||
}
|
||||
|
||||
pub fn get_element_type(&self) -> &Type {
|
||||
&self.element_type
|
||||
}
|
||||
// pub fn get_element_type(&self) -> &Type {
|
||||
// &self.element_type
|
||||
// }
|
||||
|
||||
// Stringify cstruct for pretty printing something like:
|
||||
// <CStruct( u8, i32, size = 8 )>
|
||||
|
@ -89,6 +99,64 @@ impl CArr {
|
|||
}
|
||||
}
|
||||
|
||||
impl NativeSize for CArr {
|
||||
fn get_size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
impl NativeSignedness for CArr {
|
||||
fn get_signedness(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
impl NativeConvert for CArr {
|
||||
// FIXME: FfiBox, FfiRef support required
|
||||
unsafe fn luavalue_into<'lua>(
|
||||
&self,
|
||||
lua: &'lua Lua,
|
||||
offset: isize,
|
||||
data_handle: &Ref<dyn NativeDataHandle>,
|
||||
value: LuaValue<'lua>,
|
||||
) -> LuaResult<()> {
|
||||
let LuaValue::Table(ref table) = value else {
|
||||
return Err(LuaError::external("Value is not a table"));
|
||||
};
|
||||
for i in 0..self.length {
|
||||
let field_offset = (i * self.field_size) as isize;
|
||||
let data: LuaValue = table.get(i + 1)?;
|
||||
|
||||
self.conv.as_ref().unwrap().luavalue_into(
|
||||
lua,
|
||||
field_offset + offset,
|
||||
data_handle,
|
||||
data,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn luavalue_from<'lua>(
|
||||
&self,
|
||||
lua: &'lua Lua,
|
||||
offset: isize,
|
||||
data_handle: &Ref<dyn NativeDataHandle>,
|
||||
) -> LuaResult<LuaValue<'lua>> {
|
||||
let table = lua.create_table_with_capacity(self.length, 0)?;
|
||||
for i in 0..self.length {
|
||||
let field_offset = (i * self.field_size) as isize;
|
||||
table.set(
|
||||
i + 1,
|
||||
self.conv.as_ref().unwrap().luavalue_from(
|
||||
lua,
|
||||
field_offset + offset,
|
||||
data_handle,
|
||||
)?,
|
||||
)?;
|
||||
}
|
||||
Ok(LuaValue::Table(table))
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaUserData for CArr {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("size", |_, this| Ok(this.get_size()));
|
||||
|
@ -109,6 +177,44 @@ impl LuaUserData for CArr {
|
|||
Err(LuaError::external("Out of index"))
|
||||
}
|
||||
});
|
||||
methods.add_method("box", |lua, this, table: LuaValue| {
|
||||
let result = lua.create_userdata(FfiBox::new(this.get_size()))?;
|
||||
|
||||
unsafe { this.luavalue_into(lua, 0, &result.get_data_handle()?, table)? };
|
||||
Ok(result)
|
||||
});
|
||||
methods.add_method(
|
||||
"from",
|
||||
|lua, this, (userdata, offset): (LuaAnyUserData, Option<isize>)| {
|
||||
let offset = offset.unwrap_or(0);
|
||||
|
||||
let data_handle = &userdata.get_data_handle()?;
|
||||
if !data_handle.check_boundary(offset, this.get_size()) {
|
||||
return Err(LuaError::external("Out of bounds"));
|
||||
}
|
||||
if !data_handle.check_readable(&userdata, offset, this.get_size()) {
|
||||
return Err(LuaError::external("Unreadable data handle"));
|
||||
}
|
||||
|
||||
unsafe { this.luavalue_from(lua, offset, data_handle) }
|
||||
},
|
||||
);
|
||||
methods.add_method(
|
||||
"into",
|
||||
|lua, this, (userdata, value, offset): (LuaAnyUserData, LuaValue, Option<isize>)| {
|
||||
let offset = offset.unwrap_or(0);
|
||||
|
||||
let data_handle = &userdata.get_data_handle()?;
|
||||
if !data_handle.check_boundary(offset, this.size) {
|
||||
return Err(LuaError::external("Out of bounds"));
|
||||
}
|
||||
if !data_handle.checek_writable(&userdata, offset, this.size) {
|
||||
return Err(LuaError::external("Unwritable data handle"));
|
||||
}
|
||||
|
||||
unsafe { this.luavalue_into(lua, offset, data_handle, value) }
|
||||
},
|
||||
);
|
||||
methods.add_function("ptr", |lua, this: LuaAnyUserData| {
|
||||
let pointer = CPtr::new_from_lua_userdata(lua, &this)?;
|
||||
Ok(pointer)
|
||||
|
|
|
@ -6,10 +6,9 @@ use libffi::{low, middle::Type, raw};
|
|||
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::CTYPE_STATIC;
|
||||
use super::c_type::CTypeStatic;
|
||||
use super::types::get_ctype_conv;
|
||||
use super::{CArr, CPtr, CStruct};
|
||||
use super::{
|
||||
association_names::CTYPE_STATIC, types::get_ctype_conv, CArr, CPtr, CStruct, CTypeStatic,
|
||||
};
|
||||
use crate::ffi::{ffi_association::get_association, NativeConvert, FFI_STATUS_NAMES};
|
||||
|
||||
// Get the NativeConvert handle from the type UserData
|
||||
|
|
|
@ -88,7 +88,7 @@ impl<T> NativeSize for CType<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CType<T: ?Sized> {
|
||||
pub struct CType<T> {
|
||||
// for ffi_ptrarray_to_raw?
|
||||
// libffi_cif: Cif,
|
||||
libffi_type: Type,
|
||||
|
|
|
@ -12,7 +12,7 @@ pub use self::{
|
|||
c_fn::CFn,
|
||||
c_ptr::CPtr,
|
||||
c_struct::CStruct,
|
||||
c_type::{CType, CTypeCast},
|
||||
c_type::{CType, CTypeCast, CTypeStatic},
|
||||
};
|
||||
|
||||
pub use types::create_all_c_types;
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
#![allow(clippy::inline_always)]
|
||||
|
||||
use core::ffi::*;
|
||||
use std::cell::Ref;
|
||||
use std::{any::TypeId, ops::Deref};
|
||||
use std::{any::TypeId, cell::Ref};
|
||||
|
||||
use libffi::middle::Type;
|
||||
use mlua::prelude::*;
|
||||
use num::cast::AsPrimitive;
|
||||
|
||||
use super::{CType, CTypeCast};
|
||||
use crate::ffi::{NativeConvert, NativeDataHandle, NativeSignedness};
|
||||
use crate::ffi::{NativeConvert, NativeDataHandle};
|
||||
|
||||
pub mod f32;
|
||||
pub mod f64;
|
||||
|
@ -129,120 +128,107 @@ pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserDat
|
|||
])
|
||||
}
|
||||
|
||||
macro_rules! define_ctype_size_from_userdata {
|
||||
($t:ident, $f:ty, $( $c:ty ),*) => {
|
||||
if $t.is::<CType<$f>>() {
|
||||
Ok(size_of::<$f>())
|
||||
}$( else if $t.is::<CType<$c>>() {
|
||||
Ok(size_of::<$c>())
|
||||
})* else {
|
||||
Err(LuaError::external("Unexpected type"))
|
||||
}
|
||||
};
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn ctype_size_from_userdata(this: &LuaAnyUserData) -> LuaResult<usize> {
|
||||
define_ctype_size_from_userdata!(
|
||||
this, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! define_ctype_luavalue_into_ptr {
|
||||
($lua:ident, $this:ident, $offset:ident, $data_handle:ident, $value:ident, $f:ty, $( $c:ty ),*) => {
|
||||
if $this.is::<CType<$f>>() {
|
||||
let ctype = $this.borrow::<CType<$f>>()?;
|
||||
ctype.luavalue_into($lua, $offset, $data_handle, $value)
|
||||
}$( else if $this.is::<CType<$c>>() {
|
||||
let ctype = $this.borrow::<CType<$c>>()?;
|
||||
ctype.luavalue_into($lua, $offset, $data_handle, $value)
|
||||
})* else {
|
||||
Err(LuaError::external("Unexpected type"))
|
||||
}
|
||||
};
|
||||
}
|
||||
#[inline(always)]
|
||||
pub unsafe fn ctype_luavalue_into_ptr<'lua>(
|
||||
lua: &'lua Lua,
|
||||
this: &LuaAnyUserData<'lua>,
|
||||
offset: isize,
|
||||
data_handle: &Ref<dyn NativeDataHandle>,
|
||||
value: LuaValue<'lua>,
|
||||
) -> LuaResult<()> {
|
||||
define_ctype_luavalue_into_ptr!(
|
||||
lua,
|
||||
this,
|
||||
offset,
|
||||
data_handle,
|
||||
value,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! define_ctype_luavalue_from_ptr {
|
||||
($lua:ident, $this:ident, $offset:ident, $data_handle:ident, $f:ty, $( $c:ty ),*) => {
|
||||
if $this.is::<CType<$f>>() {
|
||||
$this.borrow::<CType<$f>>()?.luavalue_from($lua, $offset, $data_handle)
|
||||
}$( else if $this.is::<CType<$c>>() {
|
||||
$this.borrow::<CType<$c>>()?.luavalue_from($lua, $offset, $data_handle)
|
||||
})* else {
|
||||
Err(LuaError::external("Unexpected type"))
|
||||
}
|
||||
};
|
||||
}
|
||||
#[inline(always)]
|
||||
pub unsafe fn ctype_luavalue_from_ptr<'lua>(
|
||||
lua: &'lua Lua,
|
||||
this: &LuaAnyUserData<'lua>,
|
||||
offset: isize,
|
||||
data_handle: &Ref<dyn NativeDataHandle>,
|
||||
) -> LuaResult<LuaValue<'lua>> {
|
||||
define_ctype_luavalue_from_ptr!(
|
||||
lua,
|
||||
this,
|
||||
offset,
|
||||
data_handle,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
f32,
|
||||
f64
|
||||
)
|
||||
}
|
||||
|
||||
// struct CastCache<'a> {
|
||||
// conv: &'a [for<'lua> fn(lua: &'lua Lua)],
|
||||
// ud: Box<[*const dyn NativeConvert]>,
|
||||
// macro_rules! define_ctype_size_from_userdata {
|
||||
// ($t:ident, $f:ty, $( $c:ty ),*) => {
|
||||
// if $t.is::<CType<$f>>() {
|
||||
// Ok(size_of::<$f>())
|
||||
// }$( else if $t.is::<CType<$c>>() {
|
||||
// Ok(size_of::<$c>())
|
||||
// })* else {
|
||||
// Err(LuaError::external("Unexpected type"))
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// #[inline(always)]
|
||||
// pub fn ctype_size_from_userdata(this: &LuaAnyUserData) -> LuaResult<usize> {
|
||||
// define_ctype_size_from_userdata!(
|
||||
// this, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64
|
||||
// )
|
||||
// }
|
||||
|
||||
// fn test<'a>(ud: &'a LuaAnyUserData) -> LuaResult<Box<CastCache<'a>>> {
|
||||
// Box::new([(ud.to_pointer() as *const CType<u8>) as *const dyn NativeConvert])
|
||||
// let ff: for<'lua> unsafe fn(
|
||||
// macro_rules! define_ctype_luavalue_into_ptr {
|
||||
// ($lua:ident, $this:ident, $offset:ident, $data_handle:ident, $value:ident, $f:ty, $( $c:ty ),*) => {
|
||||
// if $this.is::<CType<$f>>() {
|
||||
// let ctype = $this.borrow::<CType<$f>>()?;
|
||||
// ctype.luavalue_into($lua, $offset, $data_handle, $value)
|
||||
// }$( else if $this.is::<CType<$c>>() {
|
||||
// let ctype = $this.borrow::<CType<$c>>()?;
|
||||
// ctype.luavalue_into($lua, $offset, $data_handle, $value)
|
||||
// })* else {
|
||||
// Err(LuaError::external("Unexpected type"))
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// #[inline(always)]
|
||||
// pub unsafe fn ctype_luavalue_into_ptr<'lua>(
|
||||
// lua: &'lua Lua,
|
||||
// type_userdata: &LuaAnyUserData<'lua>,
|
||||
// this: &LuaAnyUserData<'lua>,
|
||||
// offset: isize,
|
||||
// data_handle: &Ref<dyn NativeDataHandle>,
|
||||
// value: LuaValue<'lua>,
|
||||
// ) -> LuaResult<()> = || CType::<f32>::luavalue_into;
|
||||
// ) -> LuaResult<()> {
|
||||
// define_ctype_luavalue_into_ptr!(
|
||||
// lua,
|
||||
// this,
|
||||
// offset,
|
||||
// data_handle,
|
||||
// value,
|
||||
// u8,
|
||||
// u16,
|
||||
// u32,
|
||||
// u64,
|
||||
// u128,
|
||||
// i8,
|
||||
// i16,
|
||||
// i32,
|
||||
// i64,
|
||||
// i128,
|
||||
// f32,
|
||||
// f64
|
||||
// )
|
||||
// }
|
||||
|
||||
// macro_rules! define_ctype_luavalue_from_ptr {
|
||||
// ($lua:ident, $this:ident, $offset:ident, $data_handle:ident, $f:ty, $( $c:ty ),*) => {
|
||||
// if $this.is::<CType<$f>>() {
|
||||
// $this.borrow::<CType<$f>>()?.luavalue_from($lua, $offset, $data_handle)
|
||||
// }$( else if $this.is::<CType<$c>>() {
|
||||
// $this.borrow::<CType<$c>>()?.luavalue_from($lua, $offset, $data_handle)
|
||||
// })* else {
|
||||
// Err(LuaError::external("Unexpected type"))
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// #[inline(always)]
|
||||
// pub unsafe fn ctype_luavalue_from_ptr<'lua>(
|
||||
// lua: &'lua Lua,
|
||||
// this: &LuaAnyUserData<'lua>,
|
||||
// offset: isize,
|
||||
// data_handle: &Ref<dyn NativeDataHandle>,
|
||||
// ) -> LuaResult<LuaValue<'lua>> {
|
||||
// define_ctype_luavalue_from_ptr!(
|
||||
// lua,
|
||||
// this,
|
||||
// offset,
|
||||
// data_handle,
|
||||
// u8,
|
||||
// u16,
|
||||
// u32,
|
||||
// u64,
|
||||
// u128,
|
||||
// i8,
|
||||
// i16,
|
||||
// i32,
|
||||
// i64,
|
||||
// i128,
|
||||
// f32,
|
||||
// f64
|
||||
// )
|
||||
// }
|
||||
|
||||
// Use UB method, but safe. because we use ffi_association to ensure children alive
|
||||
// Much faster then get NativeConvert handle everytime from lua table
|
||||
// it's spam of table.get(), if ud.is::<T>() { ud.borrow::<T>()? ... }
|
||||
macro_rules! define_get_ctype_conv {
|
||||
($userdata:ident, $f:ty, $( $c:ty ),*) => {
|
||||
if $userdata.is::<CType<$f>>() {
|
||||
|
|
|
@ -3,10 +3,12 @@ use std::sync::LazyLock;
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::REF_INNER;
|
||||
use super::ffi_association::set_association;
|
||||
use super::ffi_native::NativeDataHandle;
|
||||
use super::ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag, FfiRefFlagList};
|
||||
use super::{
|
||||
association_names::REF_INNER,
|
||||
ffi_association::set_association,
|
||||
ffi_ref::{FfiRef, FfiRefBounds, FfiRefFlag, FfiRefFlagList},
|
||||
NativeDataHandle,
|
||||
};
|
||||
|
||||
static BOX_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
|
||||
FfiRefFlagList::new(&[
|
||||
|
|
0
crates/lune-std-ffi/src/ffi/ffi_func.rs
Normal file
0
crates/lune-std-ffi/src/ffi/ffi_func.rs
Normal file
|
@ -1,29 +0,0 @@
|
|||
#![allow(clippy::inline_always)]
|
||||
|
||||
// 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",
|
||||
];
|
||||
|
||||
#[allow(unused)]
|
||||
pub mod bit_mask {
|
||||
pub const U8_MASK1: u8 = 1;
|
||||
pub const U8_MASK2: u8 = 2;
|
||||
pub const U8_MASK3: u8 = 4;
|
||||
pub const U8_MASK4: u8 = 8;
|
||||
pub const U8_MASK5: u8 = 16;
|
||||
pub const U8_MASK6: u8 = 32;
|
||||
pub const U8_MASK7: u8 = 64;
|
||||
pub const U8_MASK8: u8 = 128;
|
||||
|
||||
macro_rules! U8_TEST {
|
||||
($val:expr, $mask:ident) => {
|
||||
($val & $mask != 0)
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use U8_TEST;
|
||||
}
|
|
@ -4,8 +4,11 @@ use std::sync::LazyLock;
|
|||
use dlopen2::symbor::Library;
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::ffi_association::set_association;
|
||||
use super::ffi_ref::{FfiRef, FfiRefFlag, FfiRefFlagList, UNSIZED_BOUNDS};
|
||||
use super::{
|
||||
association_names::SYM_INNER,
|
||||
ffi_association::set_association,
|
||||
ffi_ref::{FfiRef, FfiRefFlag, FfiRefFlagList, UNSIZED_BOUNDS},
|
||||
};
|
||||
|
||||
static LIB_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
|
||||
FfiRefFlagList::new(&[
|
||||
|
@ -18,8 +21,6 @@ static LIB_REF_FLAGS: LazyLock<FfiRefFlagList> = LazyLock::new(|| {
|
|||
|
||||
pub struct FfiLib(Library);
|
||||
|
||||
const SYM_INNER: &str = "__syn_inner";
|
||||
|
||||
// COMMENT HERE
|
||||
// For convenience, it would be nice to provide a way to get
|
||||
// symbols from a table with type and field names specified.
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
// relatively insecure operations, and help ensure that as little
|
||||
// data copy as possible occurs, while allowing you to do little restrictions.
|
||||
|
||||
pub struct FfiRaw();
|
||||
pub struct FfiRaw(*const ());
|
||||
|
|
|
@ -2,15 +2,19 @@ use std::ptr;
|
|||
|
||||
use mlua::prelude::*;
|
||||
|
||||
use super::association_names::REF_INNER;
|
||||
use super::ffi_association::{get_association, set_association};
|
||||
use super::ffi_native::NativeDataHandle;
|
||||
use super::{
|
||||
association_names::REF_INNER,
|
||||
ffi_association::{get_association, set_association},
|
||||
NativeDataHandle,
|
||||
};
|
||||
|
||||
mod bounds;
|
||||
mod flags;
|
||||
|
||||
pub use self::bounds::{FfiRefBounds, UNSIZED_BOUNDS};
|
||||
pub use self::flags::{FfiRefFlag, FfiRefFlagList};
|
||||
pub use self::{
|
||||
bounds::{FfiRefBounds, UNSIZED_BOUNDS},
|
||||
flags::{FfiRefFlag, FfiRefFlagList},
|
||||
};
|
||||
|
||||
// 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
|
||||
|
@ -18,8 +22,6 @@ pub use self::flags::{FfiRefFlag, FfiRefFlagList};
|
|||
// 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 (),
|
||||
pub flags: FfiRefFlagList,
|
||||
|
|
|
@ -18,6 +18,7 @@ pub use self::{
|
|||
// Named registry table names
|
||||
mod association_names {
|
||||
pub const REF_INNER: &str = "__ref_inner";
|
||||
pub const SYM_INNER: &str = "__syn_inner";
|
||||
}
|
||||
|
||||
// Converts ffi status into &str
|
||||
|
|
Loading…
Add table
Reference in a new issue