mirror of
https://github.com/lune-org/lune.git
synced 2025-04-10 21:40:54 +01:00
Implement ctype casting (#243)
This commit is contained in:
parent
d60a1b99f6
commit
6d0db930f6
20 changed files with 381 additions and 110 deletions
58
Cargo.lock
generated
58
Cargo.lock
generated
|
@ -1637,6 +1637,7 @@ dependencies = [
|
||||||
"lune-utils",
|
"lune-utils",
|
||||||
"mlua",
|
"mlua",
|
||||||
"mlua-sys",
|
"mlua-sys",
|
||||||
|
"num",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1933,6 +1934,40 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1948,6 +1983,29 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|
|
@ -15,6 +15,7 @@ workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mlua = { version = "0.9.9", features = ["luau"] }
|
mlua = { version = "0.9.9", features = ["luau"] }
|
||||||
mlua-sys = { version = "0.6.2", features = ["luau"] }
|
mlua-sys = { version = "0.6.2", features = ["luau"] }
|
||||||
|
num = "0.3.1"
|
||||||
dlopen2 = "0.6"
|
dlopen2 = "0.6"
|
||||||
|
|
||||||
libffi = "3.2.0"
|
libffi = "3.2.0"
|
||||||
|
|
|
@ -1,14 +1,9 @@
|
||||||
use std::any::Any;
|
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
use super::association_names::CARR_INNER;
|
use super::association_names::CARR_INNER;
|
||||||
use super::c_helper::{
|
use super::c_helper::{get_ensured_size, pretty_format_userdata, type_from_userdata};
|
||||||
get_ensured_size, name_from_userdata, stringify_userdata, type_from_userdata,
|
|
||||||
};
|
|
||||||
use super::c_ptr::CPtr;
|
use super::c_ptr::CPtr;
|
||||||
use super::c_type::CType;
|
|
||||||
use crate::ffi::ffi_association::{get_association, set_association};
|
use crate::ffi::ffi_association::{get_association, set_association};
|
||||||
|
|
||||||
// This is a series of some type.
|
// This is a series of some type.
|
||||||
|
@ -49,7 +44,7 @@ impl CArr {
|
||||||
luatype: &LuaAnyUserData<'lua>,
|
luatype: &LuaAnyUserData<'lua>,
|
||||||
length: usize,
|
length: usize,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
let fields = type_from_userdata(luatype)?;
|
let fields = type_from_userdata(lua, 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, luatype)?;
|
set_association(lua, CARR_INNER, &carr, luatype)?;
|
||||||
|
@ -66,7 +61,7 @@ impl CArr {
|
||||||
|
|
||||||
// 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(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
let inner: LuaValue = userdata.get("inner")?;
|
let inner: LuaValue = userdata.get("inner")?;
|
||||||
let carr = userdata.borrow::<CArr>()?;
|
let carr = userdata.borrow::<CArr>()?;
|
||||||
|
|
||||||
|
@ -75,20 +70,11 @@ impl CArr {
|
||||||
.as_userdata()
|
.as_userdata()
|
||||||
.ok_or(LuaError::external("failed to get inner type userdata."))?;
|
.ok_or(LuaError::external("failed to get inner type userdata."))?;
|
||||||
|
|
||||||
if inner.is::<CType<dyn Any>>() {
|
Ok(format!(
|
||||||
Ok(format!(
|
"{}*{}",
|
||||||
" {} ; {} ",
|
pretty_format_userdata(lua, inner)?,
|
||||||
stringify_userdata(inner)?,
|
carr.length,
|
||||||
carr.length
|
))
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(format!(
|
|
||||||
" <{}({})> ; {} ",
|
|
||||||
name_from_userdata(inner),
|
|
||||||
stringify_userdata(inner)?,
|
|
||||||
carr.length
|
|
||||||
))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(LuaError::external("failed to get inner type userdata."))
|
Err(LuaError::external("failed to get inner type userdata."))
|
||||||
}
|
}
|
||||||
|
@ -119,8 +105,8 @@ impl LuaUserData for CArr {
|
||||||
let pointer = CPtr::from_lua_userdata(lua, &this)?;
|
let pointer = CPtr::from_lua_userdata(lua, &this)?;
|
||||||
Ok(pointer)
|
Ok(pointer)
|
||||||
});
|
});
|
||||||
methods.add_meta_function(LuaMetaMethod::ToString, |_, this: LuaAnyUserData| {
|
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
||||||
let result = CArr::stringify(&this)?;
|
let result = CArr::stringify(lua, &this)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -35,11 +35,15 @@ impl CFn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_lua_table(args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
|
pub fn from_lua_table(lua: &Lua, args: LuaTable, ret: LuaAnyUserData) -> LuaResult<Self> {
|
||||||
let args = type_list_from_table(&args)?;
|
let args = type_list_from_table(lua, &args)?;
|
||||||
let ret = type_from_userdata(&ret)?;
|
let ret = type_from_userdata(lua, &ret)?;
|
||||||
Ok(Self::new(args, ret))
|
Ok(Self::new(args, ret))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LuaUserData for CFn {}
|
impl LuaUserData for CFn {
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
// methods.add_method("from", | this, |)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
use std::any::Any;
|
|
||||||
use std::ptr::{self, null_mut};
|
use std::ptr::{self, null_mut};
|
||||||
|
|
||||||
use libffi::{low, middle::Type, raw};
|
use libffi::{low, middle::Type, raw};
|
||||||
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::association_names::CTYPE_STATIC;
|
||||||
use super::c_arr::CArr;
|
use super::c_arr::CArr;
|
||||||
use super::c_ptr::CPtr;
|
use super::c_ptr::CPtr;
|
||||||
use super::c_struct::CStruct;
|
use super::c_struct::CStruct;
|
||||||
use super::c_type::CType;
|
use super::c_type::CTypeStatic;
|
||||||
|
use crate::ffi::ffi_association::get_association;
|
||||||
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
|
use crate::ffi::ffi_helper::FFI_STATUS_NAMES;
|
||||||
|
|
||||||
// get Vec<libffi_type> from table(array) of c-types userdata
|
// get Vec<libffi_type> from table(array) of c-types userdata
|
||||||
pub fn type_list_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
|
pub fn type_list_from_table(lua: &Lua, table: &LuaTable) -> LuaResult<Vec<Type>> {
|
||||||
let len: usize = table.raw_len();
|
let len: usize = table.raw_len();
|
||||||
let mut fields = Vec::with_capacity(len);
|
let mut fields = Vec::with_capacity(len);
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ pub fn type_list_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
|
||||||
let value = table.raw_get(i + 1)?;
|
let value = table.raw_get(i + 1)?;
|
||||||
match value {
|
match value {
|
||||||
LuaValue::UserData(field_type) => {
|
LuaValue::UserData(field_type) => {
|
||||||
fields.push(type_from_userdata(&field_type)?);
|
fields.push(type_from_userdata(lua, &field_type)?);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LuaError::external(format!(
|
return Err(LuaError::external(format!(
|
||||||
|
@ -36,11 +37,17 @@ pub fn type_list_from_table(table: &LuaTable) -> LuaResult<Vec<Type>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get libffi_type from any c-type userdata
|
// get libffi_type from any c-type userdata
|
||||||
pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
|
pub fn type_from_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<Type> {
|
||||||
if userdata.is::<CStruct>() {
|
if userdata.is::<CStruct>() {
|
||||||
Ok(userdata.borrow::<CStruct>()?.get_type().to_owned())
|
Ok(userdata.borrow::<CStruct>()?.get_type().to_owned())
|
||||||
} else if userdata.is::<CType<dyn Any>>() {
|
} else if let Some(t) = get_association(lua, CTYPE_STATIC, userdata)? {
|
||||||
Ok(userdata.borrow::<CType<dyn Any>>()?.get_type().to_owned())
|
Ok(t.as_userdata()
|
||||||
|
.ok_or(LuaError::external(
|
||||||
|
"Failed to get static ctype from userdata",
|
||||||
|
))?
|
||||||
|
.borrow::<CTypeStatic>()?
|
||||||
|
.libffi_type
|
||||||
|
.clone())
|
||||||
} else if userdata.is::<CArr>() {
|
} else if userdata.is::<CArr>() {
|
||||||
Ok(userdata.borrow::<CArr>()?.get_type().to_owned())
|
Ok(userdata.borrow::<CArr>()?.get_type().to_owned())
|
||||||
} else if userdata.is::<CPtr>() {
|
} else if userdata.is::<CPtr>() {
|
||||||
|
@ -59,37 +66,61 @@ pub fn type_from_userdata(userdata: &LuaAnyUserData) -> LuaResult<Type> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// stringify any c-type userdata (for recursive)
|
// stringify any c-type userdata (for recursive)
|
||||||
pub fn stringify_userdata(userdata: &LuaAnyUserData) -> LuaResult<String> {
|
pub fn stringify_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
if userdata.is::<CType<dyn Any>>() {
|
if userdata.is::<CStruct>() {
|
||||||
Ok(String::from(
|
let name = CStruct::stringify(lua, userdata)?;
|
||||||
userdata.borrow::<CType<dyn Any>>()?.stringify(),
|
|
||||||
))
|
|
||||||
} else if userdata.is::<CStruct>() {
|
|
||||||
let name = CStruct::stringify(userdata)?;
|
|
||||||
Ok(name)
|
Ok(name)
|
||||||
} else if userdata.is::<CArr>() {
|
} else if userdata.is::<CArr>() {
|
||||||
let name = CArr::stringify(userdata)?;
|
let name = CArr::stringify(lua, userdata)?;
|
||||||
Ok(name)
|
Ok(name)
|
||||||
} else if userdata.is::<CPtr>() {
|
} else if userdata.is::<CPtr>() {
|
||||||
let name: String = CPtr::stringify(userdata)?;
|
let name: String = CPtr::stringify(lua, userdata)?;
|
||||||
Ok(name)
|
Ok(name)
|
||||||
|
// Get CTypeStatic from CType<Any>
|
||||||
|
} else if let Some(t) = get_association(lua, CTYPE_STATIC, userdata)? {
|
||||||
|
Ok(String::from(
|
||||||
|
t.as_userdata()
|
||||||
|
.ok_or(LuaError::external(
|
||||||
|
"Failed to get static ctype from userdata",
|
||||||
|
))?
|
||||||
|
.borrow::<CTypeStatic>()?
|
||||||
|
.name
|
||||||
|
.unwrap_or("unnamed"),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(String::from("unnamed"))
|
Ok(String::from("unnamed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get name tag for any c-type userdata
|
// get name tag for any c-type userdata
|
||||||
pub fn name_from_userdata(userdata: &LuaAnyUserData) -> String {
|
pub fn tagname_from_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
if userdata.is::<CStruct>() {
|
Ok(if userdata.is::<CStruct>() {
|
||||||
String::from("CStruct")
|
String::from("CStruct")
|
||||||
} else if userdata.is::<CType<dyn Any>>() {
|
|
||||||
String::from("CType")
|
|
||||||
} else if userdata.is::<CArr>() {
|
} else if userdata.is::<CArr>() {
|
||||||
String::from("CArr")
|
String::from("CArr")
|
||||||
} else if userdata.is::<CPtr>() {
|
} else if userdata.is::<CPtr>() {
|
||||||
String::from("CPtr")
|
String::from("CPtr")
|
||||||
|
} else if userdata_is_ctype(lua, userdata)? {
|
||||||
|
String::from("CType")
|
||||||
} else {
|
} else {
|
||||||
String::from("unnamed")
|
String::from("unnamed")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn userdata_is_ctype(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<bool> {
|
||||||
|
Ok(get_association(lua, CTYPE_STATIC, userdata)?.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
// emulate 'print' for ctype userdata, but ctype is simplified
|
||||||
|
pub fn pretty_format_userdata(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
|
if userdata_is_ctype(lua, userdata)? {
|
||||||
|
stringify_userdata(lua, userdata)
|
||||||
|
} else {
|
||||||
|
Ok(format!(
|
||||||
|
"<{}({})>",
|
||||||
|
tagname_from_userdata(lua, userdata)?,
|
||||||
|
stringify_userdata(lua, userdata)?
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use mlua::prelude::*;
|
||||||
|
|
||||||
use super::association_names::CPTR_INNER;
|
use super::association_names::CPTR_INNER;
|
||||||
use super::c_arr::CArr;
|
use super::c_arr::CArr;
|
||||||
use super::c_helper::{name_from_userdata, stringify_userdata};
|
use super::c_helper::pretty_format_userdata;
|
||||||
use crate::ffi::ffi_association::{get_association, set_association};
|
use crate::ffi::ffi_association::{get_association, set_association};
|
||||||
|
|
||||||
pub struct CPtr();
|
pub struct CPtr();
|
||||||
|
@ -16,8 +16,8 @@ impl CPtr {
|
||||||
pub fn from_lua_userdata<'lua>(
|
pub fn from_lua_userdata<'lua>(
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
inner: &LuaAnyUserData,
|
inner: &LuaAnyUserData,
|
||||||
) -> LuaResult<LuaValue<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
let value = Self().into_lua(lua)?;
|
let value = lua.create_userdata(Self())?;
|
||||||
|
|
||||||
set_association(lua, CPTR_INNER, &value, inner)?;
|
set_association(lua, CPTR_INNER, &value, inner)?;
|
||||||
|
|
||||||
|
@ -25,18 +25,14 @@ impl CPtr {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stringify CPtr with inner ctype
|
// Stringify CPtr with inner ctype
|
||||||
pub fn stringify(userdata: &LuaAnyUserData) -> LuaResult<String> {
|
pub fn stringify(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
let inner: LuaValue = userdata.get("inner")?;
|
let inner: LuaValue = userdata.get("inner")?;
|
||||||
|
|
||||||
if inner.is_userdata() {
|
if inner.is_userdata() {
|
||||||
let inner = inner
|
let inner = inner
|
||||||
.as_userdata()
|
.as_userdata()
|
||||||
.ok_or(LuaError::external("failed to get inner type userdata."))?;
|
.ok_or(LuaError::external("failed to get inner type userdata."))?;
|
||||||
Ok(format!(
|
pretty_format_userdata(lua, inner)
|
||||||
" <{}({})> ",
|
|
||||||
name_from_userdata(inner),
|
|
||||||
stringify_userdata(inner)?,
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(LuaError::external("failed to get inner type userdata."))
|
Err(LuaError::external("failed to get inner type userdata."))
|
||||||
}
|
}
|
||||||
|
@ -67,8 +63,8 @@ impl LuaUserData for CPtr {
|
||||||
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
||||||
Ok(carr)
|
Ok(carr)
|
||||||
});
|
});
|
||||||
methods.add_meta_function(LuaMetaMethod::ToString, |_, this: LuaAnyUserData| {
|
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
||||||
let name: Result<String, LuaError> = CPtr::stringify(&this);
|
let name: Result<String, LuaError> = CPtr::stringify(lua, &this);
|
||||||
Ok(name)
|
Ok(name)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
use std::any::Any;
|
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
use libffi::{low, middle::Type, raw};
|
use libffi::{low, middle::Type, raw};
|
||||||
|
@ -8,9 +7,8 @@ use mlua::prelude::*;
|
||||||
|
|
||||||
use super::association_names::CSTRUCT_INNER;
|
use super::association_names::CSTRUCT_INNER;
|
||||||
use super::c_arr::CArr;
|
use super::c_arr::CArr;
|
||||||
use super::c_helper::{name_from_userdata, stringify_userdata, type_list_from_table};
|
use super::c_helper::{pretty_format_userdata, type_list_from_table};
|
||||||
use super::c_ptr::CPtr;
|
use super::c_ptr::CPtr;
|
||||||
use super::c_type::CType;
|
|
||||||
use crate::ffi::ffi_association::{get_association, set_association};
|
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;
|
||||||
|
|
||||||
|
@ -63,7 +61,7 @@ impl CStruct {
|
||||||
lua: &'lua Lua,
|
lua: &'lua Lua,
|
||||||
table: LuaTable<'lua>,
|
table: LuaTable<'lua>,
|
||||||
) -> LuaResult<LuaAnyUserData<'lua>> {
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
let fields = type_list_from_table(&table)?;
|
let fields = type_list_from_table(lua, &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, table)?;
|
set_association(lua, CSTRUCT_INNER, &cstruct, table)?;
|
||||||
|
@ -72,7 +70,7 @@ impl CStruct {
|
||||||
|
|
||||||
// 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(lua: &Lua, userdata: &LuaAnyUserData) -> LuaResult<String> {
|
||||||
let field: LuaValue = userdata.get("inner")?;
|
let field: LuaValue = userdata.get("inner")?;
|
||||||
if field.is_table() {
|
if field.is_table() {
|
||||||
let table = field
|
let table = field
|
||||||
|
@ -82,18 +80,7 @@ impl CStruct {
|
||||||
let mut result = String::from(" ");
|
let mut result = String::from(" ");
|
||||||
for i in 0..table.raw_len() {
|
for i in 0..table.raw_len() {
|
||||||
let child: LuaAnyUserData = table.raw_get(i + 1)?;
|
let child: LuaAnyUserData = table.raw_get(i + 1)?;
|
||||||
if child.is::<CType<dyn Any>>() {
|
result.push_str(pretty_format_userdata(lua, &child)?.as_str());
|
||||||
result.push_str(format!("{}, ", stringify_userdata(&child)?).as_str());
|
|
||||||
} else {
|
|
||||||
result.push_str(
|
|
||||||
format!(
|
|
||||||
"<{}({})>, ",
|
|
||||||
name_from_userdata(&child),
|
|
||||||
stringify_userdata(&child)?
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// size of
|
// size of
|
||||||
|
@ -151,8 +138,8 @@ impl LuaUserData for CStruct {
|
||||||
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
let carr = CArr::from_lua_userdata(lua, &this, length)?;
|
||||||
Ok(carr)
|
Ok(carr)
|
||||||
});
|
});
|
||||||
methods.add_meta_function(LuaMetaMethod::ToString, |_, this: LuaAnyUserData| {
|
methods.add_meta_function(LuaMetaMethod::ToString, |lua, this: LuaAnyUserData| {
|
||||||
let result = CStruct::stringify(&this)?;
|
let result = CStruct::stringify(lua, &this)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
#![allow(clippy::cargo_common_metadata)]
|
#![allow(clippy::cargo_common_metadata)]
|
||||||
|
|
||||||
|
use lune_utils::fmt::{pretty_format_value, ValueFormatConfig};
|
||||||
|
use num::cast::{AsPrimitive, NumCast};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::association_names::CTYPE_STATIC;
|
||||||
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_association::set_association;
|
||||||
use crate::ffi::ffi_helper::get_ptr_from_userdata;
|
use crate::ffi::ffi_helper::get_ptr_from_userdata;
|
||||||
|
|
||||||
pub struct CType<T: ?Sized> {
|
pub struct CType<T: ?Sized> {
|
||||||
|
@ -16,23 +20,57 @@ pub struct CType<T: ?Sized> {
|
||||||
libffi_type: Type,
|
libffi_type: Type,
|
||||||
size: usize,
|
size: usize,
|
||||||
name: Option<&'static str>,
|
name: Option<&'static str>,
|
||||||
|
signedness: bool,
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static CType, for borrow, is operation
|
||||||
|
pub struct CTypeStatic {
|
||||||
|
pub libffi_type: Type,
|
||||||
|
pub size: usize,
|
||||||
|
pub name: Option<&'static str>,
|
||||||
|
pub signedness: bool,
|
||||||
|
}
|
||||||
|
impl CTypeStatic {
|
||||||
|
fn new<T>(ctype: &CType<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
libffi_type: ctype.libffi_type.clone(),
|
||||||
|
size: ctype.size,
|
||||||
|
name: ctype.name,
|
||||||
|
signedness: ctype.signedness,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl LuaUserData for CTypeStatic {}
|
||||||
|
|
||||||
impl<T> CType<T>
|
impl<T> CType<T>
|
||||||
where
|
where
|
||||||
T: ?Sized,
|
Self: CTypeConvert,
|
||||||
|
T: 'static,
|
||||||
{
|
{
|
||||||
pub fn new_with_libffi_type(libffi_type: Type, name: Option<&'static str>) -> LuaResult<Self> {
|
pub fn new_with_libffi_type<'lua>(
|
||||||
|
lua: &'lua Lua,
|
||||||
|
libffi_type: Type,
|
||||||
|
signedness: bool,
|
||||||
|
name: Option<&'static str>,
|
||||||
|
) -> LuaResult<LuaAnyUserData<'lua>> {
|
||||||
// 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 {
|
|
||||||
|
let ctype = Self {
|
||||||
// libffi_cif: libffi_cfi,
|
// libffi_cif: libffi_cfi,
|
||||||
libffi_type,
|
libffi_type,
|
||||||
size,
|
size,
|
||||||
name,
|
name,
|
||||||
_phantom: PhantomData {},
|
signedness,
|
||||||
})
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
let userdata_static = lua.create_any_userdata(CTypeStatic::new::<T>(&ctype))?;
|
||||||
|
let userdata = lua.create_userdata(ctype)?;
|
||||||
|
|
||||||
|
set_association(lua, CTYPE_STATIC, &userdata, &userdata_static)?;
|
||||||
|
|
||||||
|
Ok(userdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_type(&self) -> &Type {
|
pub fn get_type(&self) -> &Type {
|
||||||
|
@ -45,9 +83,19 @@ where
|
||||||
None => "unnamed",
|
None => "unnamed",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast_failed_with(&self, into_ctype: &LuaAnyUserData) -> LuaError {
|
||||||
|
let config = ValueFormatConfig::new();
|
||||||
|
LuaError::external(format!(
|
||||||
|
"Cannot cast <CType({})> to {}",
|
||||||
|
self.stringify(),
|
||||||
|
pretty_format_value(&LuaValue::UserData(into_ctype.to_owned()), &config)
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PtrHandle {
|
// Handle C data, provide type conversion between luavalue and c-type
|
||||||
|
pub trait CTypeConvert {
|
||||||
// Convert luavalue into data, then write into ptr
|
// Convert luavalue into data, then write into ptr
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()>;
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()>;
|
||||||
|
|
||||||
|
@ -79,12 +127,53 @@ pub trait PtrHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CTypeNumCast<T>
|
||||||
|
where
|
||||||
|
T: NumCast,
|
||||||
|
{
|
||||||
|
// Cast T as U
|
||||||
|
fn cast_userdata<U>(from: &LuaAnyUserData, into: &LuaAnyUserData) -> LuaResult<()>
|
||||||
|
where
|
||||||
|
T: AsPrimitive<U>,
|
||||||
|
U: 'static + Copy,
|
||||||
|
{
|
||||||
|
let from_ptr = unsafe { get_ptr_from_userdata(from, None)?.cast::<T>() };
|
||||||
|
let into_ptr = unsafe { get_ptr_from_userdata(into, None)?.cast::<U>() };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*into_ptr = (*from_ptr).as_();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cast_userdata_if_type_match<U>(
|
||||||
|
ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<Option<()>>
|
||||||
|
where
|
||||||
|
T: AsPrimitive<U>,
|
||||||
|
U: 'static + Copy,
|
||||||
|
{
|
||||||
|
if ctype.is::<CType<U>>() {
|
||||||
|
Self::cast_userdata(from, into)?;
|
||||||
|
Ok(Some(()))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> LuaUserData for CType<T>
|
impl<T> LuaUserData for CType<T>
|
||||||
where
|
where
|
||||||
Self: Sized + PtrHandle,
|
Self: CTypeConvert,
|
||||||
|
T: 'static,
|
||||||
{
|
{
|
||||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
fields.add_field_method_get("size", |_, this| Ok(this.size));
|
||||||
|
fields.add_meta_field(LuaMetaMethod::Type, "CType");
|
||||||
|
fields.add_field_method_get("signedness", |_, this| Ok(this.signedness));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
|
|
@ -14,4 +14,5 @@ mod association_names {
|
||||||
pub const CPTR_INNER: &str = "__cptr_inner";
|
pub const CPTR_INNER: &str = "__cptr_inner";
|
||||||
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";
|
||||||
|
pub const CTYPE_STATIC: &str = "__ctype_static";
|
||||||
}
|
}
|
||||||
|
|
68
crates/lune-std-ffi/src/c/types/c_char.rs
Normal file
68
crates/lune-std-ffi/src/c/types/c_char.rs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
use core::ffi::*;
|
||||||
|
|
||||||
|
use libffi::middle::Type;
|
||||||
|
use mlua::prelude::*;
|
||||||
|
|
||||||
|
use super::super::c_type::{CType, CTypeConvert, CTypeNumCast};
|
||||||
|
use crate::ffi::ffi_platform::CHAR_IS_SIGNED;
|
||||||
|
|
||||||
|
impl CTypeConvert for CType<c_char> {
|
||||||
|
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_char;
|
||||||
|
unsafe {
|
||||||
|
*(ptr.cast::<c_char>()) = value;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn ptr_into_luavalue(lua: &Lua, ptr: *mut ()) -> LuaResult<LuaValue> {
|
||||||
|
let value = unsafe { (*ptr.cast::<c_char>()).into_lua(lua)? };
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CType<c_char> {
|
||||||
|
fn cast(
|
||||||
|
&self,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
Self::cast_userdata_if_type_match::<c_float>(into_ctype, from, into)?
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_double>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_char>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_long>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(into_ctype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CTypeNumCast<c_char> for CType<c_char> {}
|
||||||
|
|
||||||
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
|
Ok((
|
||||||
|
"char",
|
||||||
|
CType::<c_char>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
if CHAR_IS_SIGNED {
|
||||||
|
Type::c_schar()
|
||||||
|
} else {
|
||||||
|
Type::c_uchar()
|
||||||
|
},
|
||||||
|
CHAR_IS_SIGNED,
|
||||||
|
Some("char"),
|
||||||
|
)?,
|
||||||
|
))
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
use core::ffi::c_int;
|
use core::ffi::*;
|
||||||
|
|
||||||
use libffi::middle::Type;
|
use libffi::middle::Type;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
use super::super::c_type::{CType, PtrHandle};
|
use super::super::c_type::{CType, CTypeConvert, CTypeNumCast};
|
||||||
|
|
||||||
impl PtrHandle for CType<c_int> {
|
impl CTypeConvert for CType<c_int> {
|
||||||
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
fn luavalue_into_ptr(value: LuaValue, ptr: *mut ()) -> LuaResult<()> {
|
||||||
let value = match value {
|
let value = match value {
|
||||||
LuaValue::Integer(t) => t,
|
LuaValue::Integer(t) => t,
|
||||||
|
@ -28,11 +28,36 @@ impl PtrHandle for CType<c_int> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CType<c_int> {
|
impl CType<c_int> {
|
||||||
fn new() -> LuaResult<Self> {
|
fn cast(
|
||||||
Self::new_with_libffi_type(Type::c_int(), Some("int"))
|
&self,
|
||||||
|
into_ctype: &LuaAnyUserData,
|
||||||
|
from: &LuaAnyUserData,
|
||||||
|
into: &LuaAnyUserData,
|
||||||
|
) -> LuaResult<()> {
|
||||||
|
Self::cast_userdata_if_type_match::<c_float>(into_ctype, from, into)?
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_double>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_char>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.or(Self::cast_userdata_if_type_match::<c_long>(
|
||||||
|
into_ctype, from, into,
|
||||||
|
)?)
|
||||||
|
.ok_or_else(|| self.cast_failed_with(into_ctype))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTypeNumCast<c_int> for CType<c_int> {}
|
||||||
|
|
||||||
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
pub fn get_export(lua: &Lua) -> LuaResult<(&'static str, LuaAnyUserData)> {
|
||||||
Ok(("int", lua.create_userdata(CType::<c_int>::new()?)?))
|
Ok((
|
||||||
|
"int",
|
||||||
|
CType::<c_int>::new_with_libffi_type(
|
||||||
|
lua,
|
||||||
|
Type::c_int(),
|
||||||
|
c_int::MIN.unsigned_abs() != 0,
|
||||||
|
Some("int"),
|
||||||
|
)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
mod c_char;
|
||||||
mod c_int;
|
mod c_int;
|
||||||
|
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
// export all default c-types
|
// export all default c-types
|
||||||
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
pub fn create_all_types(lua: &Lua) -> LuaResult<Vec<(&'static str, LuaAnyUserData)>> {
|
||||||
Ok(vec![c_int::get_export(lua)?])
|
Ok(vec![c_int::get_export(lua)?, c_char::get_export(lua)?])
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,14 @@
|
||||||
// uservalue operations cannot be performed directly,
|
// uservalue operations cannot be performed directly,
|
||||||
// so this is the best solution for now.
|
// so this is the best solution for now.
|
||||||
// If the dependency is deep, the value may be completely destroyed when
|
// If the dependency is deep, the value may be completely destroyed when
|
||||||
// gc is performed multiple times. As an example, there is the following case:
|
// gc is performed multiple times. To prevent this situation, FFI 'copies'
|
||||||
|
// dependency if possible.
|
||||||
//
|
//
|
||||||
// ffi.i32:ptr():ptr()
|
// ffi.i32:ptr():ptr()
|
||||||
|
// Something like this, every pointer type will have various inner field.
|
||||||
|
//
|
||||||
// box:ref():ref()
|
// box:ref():ref()
|
||||||
|
// But, in this case,
|
||||||
//
|
//
|
||||||
// Since the outermost pointer holds the definition for the pointer
|
// Since the outermost pointer holds the definition for the pointer
|
||||||
// type inside it, only the outermost type will be removed on the first gc.
|
// type inside it, only the outermost type will be removed on the first gc.
|
||||||
|
|
|
@ -74,11 +74,15 @@ impl FfiBox {
|
||||||
t
|
t
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
ptr = unsafe { target.get_ptr().offset(t) };
|
ptr = unsafe { target.get_ptr().byte_offset(t) };
|
||||||
bounds = bounds.offset(t);
|
bounds = bounds.offset(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), Some(bounds)))?;
|
// Lua should not be able to deref a box that refers to a box managed by Lua.
|
||||||
|
// To deref a box space is to allow lua to read any space,
|
||||||
|
// which has security issues and is ultimately dangerous.
|
||||||
|
// Therefore, box:ref():deref() is not allowed.
|
||||||
|
let luaref = lua.create_userdata(FfiRef::new(ptr.cast(), false, Some(bounds)))?;
|
||||||
|
|
||||||
// Makes box alive longer then ref
|
// Makes box alive longer then ref
|
||||||
set_association(lua, REF_INNER, &luaref, &this)?;
|
set_association(lua, REF_INNER, &luaref, &this)?;
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub const FFI_STATUS_NAMES: [&str; 4] = [
|
||||||
"ffi_status_FFI_BAD_ARGTYPE",
|
"ffi_status_FFI_BAD_ARGTYPE",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// TODO: using trait
|
||||||
// Get raw pointer from userdata
|
// Get raw pointer from userdata
|
||||||
// TODO: boundary check
|
// TODO: boundary check
|
||||||
pub unsafe fn get_ptr_from_userdata(
|
pub unsafe fn get_ptr_from_userdata(
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl FfiLib {
|
||||||
.map_err(|err| LuaError::external(format!("{err}")))?
|
.map_err(|err| LuaError::external(format!("{err}")))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let luasym = lua.create_userdata(FfiRef::new((*sym).cast(), None))?;
|
let luasym = lua.create_userdata(FfiRef::new((*sym).cast(), true, None))?;
|
||||||
|
|
||||||
set_association(lua, SYM_INNER, &luasym, &this)?;
|
set_association(lua, SYM_INNER, &luasym, &this)?;
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,17 @@ use super::ffi_bounds::FfiRefBounds;
|
||||||
|
|
||||||
pub struct FfiRef {
|
pub struct FfiRef {
|
||||||
ptr: *mut (),
|
ptr: *mut (),
|
||||||
|
dereferenceable: bool,
|
||||||
range: Option<FfiRefBounds>,
|
range: Option<FfiRefBounds>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FfiRef {
|
impl FfiRef {
|
||||||
pub fn new(ptr: *mut (), range: Option<FfiRefBounds>) -> Self {
|
pub fn new(ptr: *mut (), dereferenceable: bool, range: Option<FfiRefBounds>) -> Self {
|
||||||
Self { ptr, range }
|
Self {
|
||||||
|
ptr,
|
||||||
|
dereferenceable,
|
||||||
|
range,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make FfiRef from ref
|
// Make FfiRef from ref
|
||||||
|
@ -33,16 +38,15 @@ impl FfiRef {
|
||||||
|
|
||||||
let luaref = lua.create_userdata(FfiRef::new(
|
let luaref = lua.create_userdata(FfiRef::new(
|
||||||
ptr::from_ref(&target.ptr) as *mut (),
|
ptr::from_ref(&target.ptr) as *mut (),
|
||||||
|
true,
|
||||||
Some(FfiRefBounds {
|
Some(FfiRefBounds {
|
||||||
low: 0,
|
low: 0,
|
||||||
high: size_of::<usize>(),
|
high: size_of::<usize>(),
|
||||||
}),
|
}),
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
// If the ref holds a box, make sure the new ref also holds the box
|
// If the ref holds a box, make sure the new ref also holds the box by holding ref
|
||||||
if let Some(t) = get_association(lua, REF_INNER, &this)? {
|
set_association(lua, REF_INNER, &luaref, &this)?;
|
||||||
set_association(lua, REF_INNER, &luaref, t)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(luaref)
|
Ok(luaref)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +56,8 @@ impl FfiRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn deref(&self) -> Self {
|
pub unsafe fn deref(&self) -> Self {
|
||||||
Self::new(*self.ptr.cast::<*mut ()>(), None)
|
// FIXME
|
||||||
|
Self::new(*self.ptr.cast::<*mut ()>(), true, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
pub unsafe fn offset(&self, offset: isize) -> LuaResult<Self> {
|
||||||
|
@ -67,7 +72,8 @@ impl FfiRef {
|
||||||
let range = self.range.as_ref().map(|t| t.offset(offset));
|
let range = self.range.as_ref().map(|t| t.offset(offset));
|
||||||
|
|
||||||
Ok(Self::new(
|
Ok(Self::new(
|
||||||
self.ptr.cast::<u8>().offset(offset).cast(),
|
self.ptr.byte_offset(offset),
|
||||||
|
self.dereferenceable,
|
||||||
range,
|
range,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -81,14 +87,22 @@ impl LuaUserData for FfiRef {
|
||||||
let result = lua.create_userdata(unsafe { ffiref.deref() })?;
|
let result = lua.create_userdata(unsafe { ffiref.deref() })?;
|
||||||
|
|
||||||
if let Some(t) = inner {
|
if let Some(t) = inner {
|
||||||
|
// if let Some(u) = get_association(lua, regname, value) {}
|
||||||
set_association(lua, REF_INNER, &result, &t)?;
|
set_association(lua, REF_INNER, &result, &t)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
});
|
});
|
||||||
methods.add_method("offset", |_, this, offset: isize| {
|
methods.add_function("offset", |lua, (this, offset): (LuaAnyUserData, isize)| {
|
||||||
let ffiref = unsafe { this.offset(offset)? };
|
let ffiref = unsafe { this.borrow::<FfiRef>()?.offset(offset)? };
|
||||||
Ok(ffiref)
|
let userdata = lua.create_userdata(ffiref)?;
|
||||||
|
|
||||||
|
// 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, &userdata, t)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(userdata)
|
||||||
});
|
});
|
||||||
methods.add_function("ref", |lua, this: LuaAnyUserData| {
|
methods.add_function("ref", |lua, this: LuaAnyUserData| {
|
||||||
let ffiref = FfiRef::luaref(lua, this)?;
|
let ffiref = FfiRef::luaref(lua, this)?;
|
||||||
|
|
|
@ -33,8 +33,8 @@ pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
let cstruct = CStruct::from_lua_table(lua, types)?;
|
let cstruct = CStruct::from_lua_table(lua, types)?;
|
||||||
Ok(cstruct)
|
Ok(cstruct)
|
||||||
})?
|
})?
|
||||||
.with_function("fn", |_, (args, ret): (LuaTable, LuaAnyUserData)| {
|
.with_function("fn", |lua, (args, ret): (LuaTable, LuaAnyUserData)| {
|
||||||
let cfn = CFn::from_lua_table(args, ret)?;
|
let cfn = CFn::from_lua_table(lua, args, ret)?;
|
||||||
Ok(cfn)
|
Ok(cfn)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
- [ ] Add docs
|
- [ ] Add docs
|
||||||
- [ ] Typing
|
- [ ] Typing
|
||||||
|
|
||||||
|
pragma pack?
|
||||||
|
|
||||||
# Raw
|
# Raw
|
||||||
|
|
||||||
- [ ] Raw:toRef()
|
- [ ] Raw:toRef()
|
||||||
|
|
Loading…
Add table
Reference in a new issue