Add ctype new support
This commit is contained in:
parent
0fd59f6874
commit
40478fb7de
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -812,7 +812,6 @@ dependencies = [
|
|||||||
"luaify",
|
"luaify",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"simdutf8",
|
"simdutf8",
|
||||||
"static_assertions",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1334,12 +1333,6 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -12,11 +12,22 @@ pub fn type_id<T: 'static>() -> u64 {
|
|||||||
hash.finish()
|
hash.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! export {
|
||||||
|
($($fn:expr),+ $(,)?) => {
|
||||||
|
// this ensures ffi function symbol exports are actually present in the resulting binary,
|
||||||
|
// otherwise they may get dead code-eliminated before it reaches the linker
|
||||||
|
#[used]
|
||||||
|
static __FFI_EXPORTS: &[fn()] = unsafe {
|
||||||
|
&[$(::std::mem::transmute($fn as *const ())),*]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! display {
|
macro_rules! display {
|
||||||
($($fmt:expr),+) => {{ crate::__internal::disp(move |f| write!(f, $($fmt),+)) }};
|
($($fmt:expr),+) => {{ crate::__internal::disp(move |f| write!(f, $($fmt),+)) }};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use display;
|
pub(crate) use {display, export};
|
||||||
|
|
||||||
pub fn disp(f: impl Fn(&mut Formatter) -> fmt::Result) -> impl Display {
|
pub fn disp(f: impl Fn(&mut Formatter) -> fmt::Result) -> impl Display {
|
||||||
struct Disp<F: Fn(&mut Formatter) -> fmt::Result>(F);
|
struct Disp<F: Fn(&mut Formatter) -> fmt::Result>(F);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::__internal::{disp, display, write_sep};
|
use crate::__internal::{disp, display, export, write_sep};
|
||||||
pub use luaffi_impl::*;
|
pub use luaffi_impl::*;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
@ -31,6 +31,8 @@ unsafe extern "C" fn __is_utf8(ptr: *const u8, len: usize) -> bool {
|
|||||||
simdutf8::basic::from_utf8(unsafe { slice::from_raw_parts(ptr, len) }).is_ok()
|
simdutf8::basic::from_utf8(unsafe { slice::from_raw_parts(ptr, len) }).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export![__keep, __is_utf8];
|
||||||
|
|
||||||
const CACHE_LIBS: &[(&str, &str)] = &[
|
const CACHE_LIBS: &[(&str, &str)] = &[
|
||||||
("table", "table"),
|
("table", "table"),
|
||||||
("string", "string"),
|
("string", "string"),
|
||||||
@ -47,7 +49,7 @@ const CACHE_LIBS: &[(&str, &str)] = &[
|
|||||||
];
|
];
|
||||||
|
|
||||||
// https://www.lua.org/manual/5.1/manual.html#5.1
|
// https://www.lua.org/manual/5.1/manual.html#5.1
|
||||||
const CACHE_GLOBALS: &[(&str, &str)] = &[
|
const CACHE_LOCALS: &[(&str, &str)] = &[
|
||||||
// base
|
// base
|
||||||
("assert", "assert"),
|
("assert", "assert"),
|
||||||
("error", "error"),
|
("error", "error"),
|
||||||
@ -86,14 +88,16 @@ const CACHE_GLOBALS: &[(&str, &str)] = &[
|
|||||||
("__fmod", "math.fmod"),
|
("__fmod", "math.fmod"),
|
||||||
// coroutine
|
// coroutine
|
||||||
("__yield", "coroutine.yield"),
|
("__yield", "coroutine.yield"),
|
||||||
|
// package
|
||||||
|
("__preload", "package.preload"),
|
||||||
// debug
|
// debug
|
||||||
("__traceback", "debug.traceback"),
|
("__traceback", "debug.traceback"),
|
||||||
// ffi
|
// ffi
|
||||||
("__C", "ffi.C"),
|
("__C", "ffi.C"),
|
||||||
|
("__ct", "{}"),
|
||||||
("__cdef", "ffi.cdef"),
|
("__cdef", "ffi.cdef"),
|
||||||
("__cnew", "ffi.new"),
|
("__new", "ffi.new"),
|
||||||
("__ctype", "ffi.typeof"),
|
("__typeof", "ffi.typeof"),
|
||||||
("__ctypes", "{}"),
|
|
||||||
("__istype", "ffi.istype"),
|
("__istype", "ffi.istype"),
|
||||||
("__metatype", "ffi.metatype"),
|
("__metatype", "ffi.metatype"),
|
||||||
("__cast", "ffi.cast"),
|
("__cast", "ffi.cast"),
|
||||||
@ -117,7 +121,7 @@ const CACHE_GLOBALS: &[(&str, &str)] = &[
|
|||||||
fn cache_local(f: &mut Formatter, list: &[(&str, &str)]) -> fmt::Result {
|
fn cache_local(f: &mut Formatter, list: &[(&str, &str)]) -> fmt::Result {
|
||||||
write!(f, "local ")?;
|
write!(f, "local ")?;
|
||||||
write_sep(f, ", ", list.iter().map(|(s, _)| s))?;
|
write_sep(f, ", ", list.iter().map(|(s, _)| s))?;
|
||||||
write!(f, "\n = ")?;
|
write!(f, " = ")?;
|
||||||
write_sep(f, ", ", list.iter().map(|(_, s)| s))?;
|
write_sep(f, ", ", list.iter().map(|(_, s)| s))?;
|
||||||
writeln!(f, ";")
|
writeln!(f, ";")
|
||||||
}
|
}
|
||||||
@ -141,7 +145,7 @@ impl Registry {
|
|||||||
pub fn include<T: Type>(&mut self) -> &mut Self {
|
pub fn include<T: Type>(&mut self) -> &mut Self {
|
||||||
self.types
|
self.types
|
||||||
.insert(T::name().to_string())
|
.insert(T::name().to_string())
|
||||||
.then(|| T::build(&mut TypeBuilder::new(self)));
|
.then(|| T::build(&mut TypeBuilder::new::<T>(self)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +153,18 @@ impl Registry {
|
|||||||
self.include::<T>()
|
self.include::<T>()
|
||||||
.funcs
|
.funcs
|
||||||
.insert(name.to_string())
|
.insert(name.to_string())
|
||||||
.then(|| writeln!(self.cdef, "{};", T::cdecl(name)).unwrap());
|
.then(|| writeln!(self.cdef, "{};", T::extern_cdecl(name)).unwrap());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preload<T: Type>(&mut self, name: impl Display) -> &mut Self {
|
||||||
|
self.include::<T>();
|
||||||
|
writeln!(
|
||||||
|
self.lua,
|
||||||
|
r#"__preload["{name}"] = function(...) return __ct.{}(...); end;"#,
|
||||||
|
T::name()
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,8 +179,8 @@ impl Display for Registry {
|
|||||||
let version = env!("CARGO_PKG_VERSION");
|
let version = env!("CARGO_PKG_VERSION");
|
||||||
writeln!(f, "--- automatically generated by {name} {version}")?;
|
writeln!(f, "--- automatically generated by {name} {version}")?;
|
||||||
cache_local(f, CACHE_LIBS)?;
|
cache_local(f, CACHE_LIBS)?;
|
||||||
cache_local(f, CACHE_GLOBALS)?;
|
cache_local(f, CACHE_LOCALS)?;
|
||||||
writeln!(f, "__cdef [[{}]];", self.cdef)?;
|
writeln!(f, "__cdef [[\n{}\n]];", self.cdef.trim())?;
|
||||||
write!(f, "{}", self.lua)
|
write!(f, "{}", self.lua)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,6 +188,10 @@ impl Display for Registry {
|
|||||||
pub unsafe trait Type {
|
pub unsafe trait Type {
|
||||||
fn name() -> impl Display;
|
fn name() -> impl Display;
|
||||||
fn cdecl(name: impl Display) -> impl Display;
|
fn cdecl(name: impl Display) -> impl Display;
|
||||||
|
fn extern_cdecl(name: impl Display) -> impl Display {
|
||||||
|
Self::cdecl(name)
|
||||||
|
}
|
||||||
|
|
||||||
fn build(b: &mut TypeBuilder);
|
fn build(b: &mut TypeBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +201,10 @@ pub struct TypeBuilder<'r> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> TypeBuilder<'r> {
|
impl<'r> TypeBuilder<'r> {
|
||||||
fn new(registry: &'r mut Registry) -> Self {
|
fn new<T: Type>(registry: &'r mut Registry) -> Self {
|
||||||
|
let ct = T::name();
|
||||||
|
let cdecl = T::cdecl("");
|
||||||
|
writeln!(registry.lua, r#"__ct.{ct} = __typeof("{cdecl}");"#).unwrap();
|
||||||
Self { registry }
|
Self { registry }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,7 +305,6 @@ pub unsafe trait Metatype {
|
|||||||
pub struct MetatypeBuilder<'r> {
|
pub struct MetatypeBuilder<'r> {
|
||||||
registry: &'r mut Registry,
|
registry: &'r mut Registry,
|
||||||
name: String,
|
name: String,
|
||||||
cdecl: String,
|
|
||||||
cdef: String,
|
cdef: String,
|
||||||
lua: String,
|
lua: String,
|
||||||
}
|
}
|
||||||
@ -293,7 +314,6 @@ impl<'r> MetatypeBuilder<'r> {
|
|||||||
Self {
|
Self {
|
||||||
registry,
|
registry,
|
||||||
name: T::Target::name().to_string(),
|
name: T::Target::name().to_string(),
|
||||||
cdecl: T::Target::cdecl("").to_string(),
|
|
||||||
cdef: String::new(),
|
cdef: String::new(),
|
||||||
lua: r#"do local __mt, __idx = {}, {}; __mt.__index = __idx; "#.into(),
|
lua: r#"do local __mt, __idx = {}, {}; __mt.__index = __idx; "#.into(),
|
||||||
}
|
}
|
||||||
@ -325,7 +345,7 @@ impl<'r> MetatypeBuilder<'r> {
|
|||||||
name: impl Display,
|
name: impl Display,
|
||||||
f: impl FnOnce(&mut MetatypeMethodBuilder),
|
f: impl FnOnce(&mut MetatypeMethodBuilder),
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
write!(self.lua, "__mt.{name} = ").unwrap();
|
write!(self.lua, "__mt.__{name} = ").unwrap();
|
||||||
f(&mut MetatypeMethodBuilder::new(self));
|
f(&mut MetatypeMethodBuilder::new(self));
|
||||||
write!(self.lua, "; ").unwrap();
|
write!(self.lua, "; ").unwrap();
|
||||||
self
|
self
|
||||||
@ -342,7 +362,6 @@ impl<'r> Drop for MetatypeBuilder<'r> {
|
|||||||
let Self {
|
let Self {
|
||||||
registry,
|
registry,
|
||||||
name,
|
name,
|
||||||
cdecl,
|
|
||||||
cdef,
|
cdef,
|
||||||
lua,
|
lua,
|
||||||
..
|
..
|
||||||
@ -350,12 +369,7 @@ impl<'r> Drop for MetatypeBuilder<'r> {
|
|||||||
|
|
||||||
registry.cdef.push_str(cdef);
|
registry.cdef.push_str(cdef);
|
||||||
registry.lua.push_str(lua);
|
registry.lua.push_str(lua);
|
||||||
|
writeln!(registry.lua, r#"__metatype(__ct.{name}, __mt); end;"#).unwrap();
|
||||||
writeln!(
|
|
||||||
registry.lua,
|
|
||||||
r#"__ctypes.{name} = __metatype("{cdecl}", __mt); end;"#
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,8 +428,6 @@ impl<'r, 'm> MetatypeMethodBuilder<'r, 'm> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn param<T: FromFfi>(&mut self, name: impl Display) -> &mut Self {
|
pub fn param<T: FromFfi>(&mut self, name: impl Display) -> &mut Self {
|
||||||
self.metatype.registry.include::<T::From>();
|
|
||||||
|
|
||||||
(!self.params.is_empty()).then(|| self.params.push_str(", "));
|
(!self.params.is_empty()).then(|| self.params.push_str(", "));
|
||||||
(!self.args.is_empty()).then(|| self.args.push_str(", "));
|
(!self.args.is_empty()).then(|| self.args.push_str(", "));
|
||||||
write!(self.params, "{name}").unwrap();
|
write!(self.params, "{name}").unwrap();
|
||||||
@ -450,6 +462,12 @@ impl<'r, 'm> MetatypeMethodBuilder<'r, 'm> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn param_ignored(&mut self) -> &mut Self {
|
||||||
|
(!self.params.is_empty()).then(|| self.params.push_str(", "));
|
||||||
|
write!(self.params, "_").unwrap();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn call<T: ToFfi>(&mut self, func: impl Display, ret: FfiReturnConvention) {
|
pub fn call<T: ToFfi>(&mut self, func: impl Display, ret: FfiReturnConvention) {
|
||||||
let Self {
|
let Self {
|
||||||
metatype,
|
metatype,
|
||||||
@ -459,8 +477,6 @@ impl<'r, 'm> MetatypeMethodBuilder<'r, 'm> {
|
|||||||
postlude,
|
postlude,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
metatype.registry.include::<T::To>();
|
|
||||||
|
|
||||||
let lua = &mut metatype.lua;
|
let lua = &mut metatype.lua;
|
||||||
write!(lua, "function({params}) {prelude}").unwrap();
|
write!(lua, "function({params}) {prelude}").unwrap();
|
||||||
|
|
||||||
@ -469,21 +485,21 @@ impl<'r, 'm> MetatypeMethodBuilder<'r, 'm> {
|
|||||||
write!(lua, "__C.{func}({args}); {postlude}end").unwrap();
|
write!(lua, "__C.{func}({args}); {postlude}end").unwrap();
|
||||||
}
|
}
|
||||||
FfiReturnConvention::ByValue => {
|
FfiReturnConvention::ByValue => {
|
||||||
let check = T::postlude("res", ret);
|
let check = T::postlude("__res", ret);
|
||||||
write!(
|
write!(
|
||||||
lua,
|
lua,
|
||||||
"local res = __C.{func}({args}); {check}{postlude}return res; end"
|
"local __res = __C.{func}({args}); {check}{postlude}return __res; end"
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
FfiReturnConvention::ByOutParam => {
|
FfiReturnConvention::ByOutParam => {
|
||||||
let ct = T::To::name();
|
let ct = T::To::name();
|
||||||
let check = T::postlude("res", ret);
|
let check = T::postlude("__res", ret);
|
||||||
write!(lua, "local res = __cnew(__ctypes.{ct}); __C.{func}(res").unwrap();
|
write!(lua, "local __res = __new(__ct.{ct}); __C.{func}(__res").unwrap();
|
||||||
if !args.is_empty() {
|
if !args.is_empty() {
|
||||||
write!(lua, ", {args}").unwrap();
|
write!(lua, ", {args}").unwrap();
|
||||||
}
|
}
|
||||||
write!(lua, "); {check}{postlude}return res; end").unwrap()
|
write!(lua, "); {check}{postlude}return __res; end").unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -560,7 +576,7 @@ macro_rules! impl_copy_primitive {
|
|||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn postlude(ret: &str, conv: FfiReturnConvention) -> impl Display {
|
fn postlude(ret: &str, conv: FfiReturnConvention) -> impl Display {
|
||||||
disp(move |f| {
|
disp(move |f| Ok({
|
||||||
match conv {
|
match conv {
|
||||||
FfiReturnConvention::Void => unreachable!(),
|
FfiReturnConvention::Void => unreachable!(),
|
||||||
FfiReturnConvention::ByValue => {},
|
FfiReturnConvention::ByValue => {},
|
||||||
@ -568,9 +584,7 @@ macro_rules! impl_copy_primitive {
|
|||||||
// the cdata containing the value and convert it to the equivalent lua value
|
// the cdata containing the value and convert it to the equivalent lua value
|
||||||
FfiReturnConvention::ByOutParam => { $(write!(f, "{ret} = {}; ", $unwrap(ret))?;)? },
|
FfiReturnConvention::ByOutParam => { $(write!(f, "{ret} = {}; ", $unwrap(ret))?;)? },
|
||||||
}
|
}
|
||||||
|
}))
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -592,7 +606,7 @@ impl_copy_primitive!(c_double, "double", "number", |n| display!("tonumber({n})")
|
|||||||
|
|
||||||
unsafe impl<T: Type> Type for *const T {
|
unsafe impl<T: Type> Type for *const T {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("ptr_const_{}", T::name())
|
display!("const_{}_ptr", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -606,7 +620,7 @@ unsafe impl<T: Type> Type for *const T {
|
|||||||
|
|
||||||
unsafe impl<T: Type> Type for *mut T {
|
unsafe impl<T: Type> Type for *mut T {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("ptr_mut_{}", T::name())
|
display!("{}_ptr", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -684,7 +698,7 @@ unsafe impl<T: Type> ToFfi for *mut T {
|
|||||||
//
|
//
|
||||||
unsafe impl<T: Type> Type for &T {
|
unsafe impl<T: Type> Type for &T {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("ref_const_{}", T::name())
|
display!("const_{}_ptr", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -698,7 +712,7 @@ unsafe impl<T: Type> Type for &T {
|
|||||||
|
|
||||||
unsafe impl<T: Type> Type for &mut T {
|
unsafe impl<T: Type> Type for &mut T {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("ref_mut_{}", T::name())
|
display!("{}_ptr", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -782,7 +796,7 @@ unsafe impl<T: Type> FromFfi for &mut T {
|
|||||||
//
|
//
|
||||||
unsafe impl<T: Type> Type for [T] {
|
unsafe impl<T: Type> Type for [T] {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("arr_{}", T::name())
|
display!("{}_arr", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -796,7 +810,7 @@ unsafe impl<T: Type> Type for [T] {
|
|||||||
|
|
||||||
unsafe impl<T: Type, const N: usize> Type for [T; N] {
|
unsafe impl<T: Type, const N: usize> Type for [T; N] {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
display!("arr{N}_{}", T::name())
|
display!("{}_arr{N}", T::name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
@ -824,20 +838,29 @@ macro_rules! impl_function {
|
|||||||
//
|
//
|
||||||
unsafe impl<$($arg: Type,)* $ret: Type> Type for $($type)+ {
|
unsafe impl<$($arg: Type,)* $ret: Type> Type for $($type)+ {
|
||||||
fn name() -> impl Display {
|
fn name() -> impl Display {
|
||||||
disp(|f| {
|
disp(|f| Ok({
|
||||||
write!(f, "fn")?;
|
write!(f, "fn_{}", $ret::name())?;
|
||||||
$(write!(f, "_{}", $arg::name())?;)*
|
$(write!(f, "_{}", $arg::name())?;)*
|
||||||
write!(f, "_{}", $ret::name())
|
}))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cdecl(name: impl Display) -> impl Display {
|
fn cdecl(name: impl Display) -> impl Display {
|
||||||
$ret::cdecl(disp(move |f| {
|
$ret::cdecl(disp(move |f| Ok({
|
||||||
let mut _n = 0;
|
let mut _n = 0;
|
||||||
write!(f, "(*{name})(")?;
|
write!(f, "(*{name})(")?;
|
||||||
$(if _n != 0 { write!(f, ", ")?; } write!(f, "{}", $arg::cdecl(""))?; _n += 1;)*
|
$(if _n != 0 { write!(f, ", ")?; } write!(f, "{}", $arg::cdecl(""))?; _n += 1;)*
|
||||||
write!(f, ")")
|
write!(f, ")")?;
|
||||||
}))
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extern_cdecl(name: impl Display) -> impl Display {
|
||||||
|
$ret::cdecl(disp(move |f| Ok({
|
||||||
|
// for top-level function declarations in cdef
|
||||||
|
let mut _n = 0;
|
||||||
|
write!(f, "{name}(")?;
|
||||||
|
$(if _n != 0 { write!(f, ", ")?; } write!(f, "{}", $arg::cdecl(""))?; _n += 1;)*
|
||||||
|
write!(f, ")")?;
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(b: &mut TypeBuilder) {
|
fn build(b: &mut TypeBuilder) {
|
||||||
|
@ -39,7 +39,7 @@ unsafe impl<T: FromFfi> FromFfi for Option<T> {
|
|||||||
fn prelude(arg: &str) -> impl Display {
|
fn prelude(arg: &str) -> impl Display {
|
||||||
let ct = Self::From::name();
|
let ct = Self::From::name();
|
||||||
display!(
|
display!(
|
||||||
"if {arg} == nil then {arg} = __cnew(__ctypes.{ct}); else {}{arg} = __cnew(__ctypes.{ct}, 1, {arg}); end; ",
|
"if {arg} == nil then {arg} = __new(__ct.{ct}); else {}{arg} = __new(__ct.{ct}, 1, {arg}); end; ",
|
||||||
T::prelude(arg)
|
T::prelude(arg)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,12 @@ use std::{fmt, ptr, slice};
|
|||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
#[cdef]
|
#[cdef]
|
||||||
pub struct lua_buf {
|
pub struct lua_buf {
|
||||||
__ptr: *mut u8,
|
__ptr: *const u8,
|
||||||
__len: usize,
|
__len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[metatype]
|
#[metatype]
|
||||||
impl lua_buf {
|
impl lua_buf {}
|
||||||
#[new]
|
|
||||||
extern "Lua-C" fn new() -> u32 {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl FromFfi for *const [u8] {
|
unsafe impl FromFfi for *const [u8] {
|
||||||
type From = lua_buf;
|
type From = lua_buf;
|
||||||
@ -33,7 +28,7 @@ unsafe impl FromFfi for *const [u8] {
|
|||||||
f,
|
f,
|
||||||
r#"if {arg} ~= nil then assert(type({arg}) == "string", "string expected in argument '{arg}', got " .. type({arg})); "#
|
r#"if {arg} ~= nil then assert(type({arg}) == "string", "string expected in argument '{arg}', got " .. type({arg})); "#
|
||||||
)?;
|
)?;
|
||||||
write!(f, "{arg} = __cnew(__ctypes.{ct}, {arg}, #{arg}); end; ")
|
write!(f, "{arg} = __new(__ct.{ct}, {arg}, #{arg}); end; ")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +64,7 @@ unsafe impl FromFfi for &str {
|
|||||||
f,
|
f,
|
||||||
r#"assert(__C.{IS_UTF8_FN}({arg}, #{arg}), "argument '{arg}' must be a valid utf-8 string"); "#
|
r#"assert(__C.{IS_UTF8_FN}({arg}, #{arg}), "argument '{arg}' must be a valid utf-8 string"); "#
|
||||||
)?;
|
)?;
|
||||||
write!(f, "{arg} = __cnew(__ctypes.{ct}, {arg}, #{arg}); ")
|
write!(f, "{arg} = __new(__ct.{ct}, {arg}, #{arg}); ")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,17 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
|||||||
.map(generate_ffi_register)
|
.map(generate_ffi_register)
|
||||||
.collect::<Result<_>>()?;
|
.collect::<Result<_>>()?;
|
||||||
|
|
||||||
|
let ffi_new_fallback = match ffi_funcs
|
||||||
|
.iter()
|
||||||
|
.find(|f| f.attrs.metatable.as_deref() == Some("new"))
|
||||||
|
{
|
||||||
|
Some(_) => None,
|
||||||
|
None => Some({
|
||||||
|
let err = format!(r#"function() error("type '{ty_name}' has no constructor"); end"#);
|
||||||
|
quote! { b.metatable_raw("new", #err); }
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
let ffi_drop_rname = format_ident!("__ffi_drop");
|
let ffi_drop_rname = format_ident!("__ffi_drop");
|
||||||
let ffi_drop_cname = format!("{ty_name}_drop");
|
let ffi_drop_cname = format!("{ty_name}_drop");
|
||||||
|
|
||||||
@ -78,6 +89,8 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
|||||||
#(#ffi_register)*
|
#(#ffi_register)*
|
||||||
#(#lua_register)*
|
#(#lua_register)*
|
||||||
|
|
||||||
|
#ffi_new_fallback
|
||||||
|
|
||||||
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_cname);
|
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_cname);
|
||||||
b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname));
|
b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname));
|
||||||
}
|
}
|
||||||
@ -100,7 +113,7 @@ struct FfiFunction {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct FfiFunctionAttrs {
|
struct FfiFunctionAttrs {
|
||||||
metatable: Option<LitStr>,
|
metatable: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ffi_functions(imp: &mut ItemImpl) -> Result<Vec<FfiFunction>> {
|
fn get_ffi_functions(imp: &mut ItemImpl) -> Result<Vec<FfiFunction>> {
|
||||||
@ -161,11 +174,11 @@ fn parse_ffi_function_attrs(attrs: &mut Vec<Attribute>) -> Result<FfiFunctionAtt
|
|||||||
while let Some(attr) = attrs.get(i) {
|
while let Some(attr) = attrs.get(i) {
|
||||||
if let Some(name) = attr.path().get_ident() {
|
if let Some(name) = attr.path().get_ident() {
|
||||||
if name == "metatable" {
|
if name == "metatable" {
|
||||||
parsed.metatable = attr.parse_args()?;
|
parsed.metatable = Some(attr.parse_args::<LitStr>()?.value());
|
||||||
attrs.remove(i);
|
attrs.remove(i);
|
||||||
continue;
|
continue;
|
||||||
} else if name == "new" {
|
} else if name == "new" {
|
||||||
parsed.metatable = parse_quote!("new");
|
parsed.metatable = Some("new".into());
|
||||||
attrs.remove(i);
|
attrs.remove(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -194,7 +207,7 @@ fn generate_ffi_wrapper(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|
||||||
for (i, param) in func.params.iter().enumerate() {
|
for (i, param) in func.params.iter().enumerate() {
|
||||||
let name = format_ident!("__arg{i}");
|
let name = format_ident!("arg{i}");
|
||||||
let ty = ¶m.ty;
|
let ty = ¶m.ty;
|
||||||
|
|
||||||
match get_ffi_arg_type(ty) {
|
match get_ffi_arg_type(ty) {
|
||||||
@ -208,10 +221,10 @@ fn generate_ffi_wrapper(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
let (ret, call) = if func.ret_by_out {
|
let (ret, call) = if func.ret_by_out {
|
||||||
// make return by out-param the first parameter
|
// make return by out-param the first parameter
|
||||||
let ret = &func.ret;
|
let ret = &func.ret;
|
||||||
params.insert(0, quote! { __out: *mut #ret });
|
params.insert(0, quote! { out: *mut #ret });
|
||||||
(
|
(
|
||||||
quote!(()),
|
quote!(()),
|
||||||
quote! { ::std::ptr::write(__out, Self::#name(#(#args),*)) },
|
quote! { ::std::ptr::write(out, Self::#name(#(#args),*)) },
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let ret = &func.ret;
|
let ret = &func.ret;
|
||||||
@ -220,9 +233,7 @@ fn generate_ffi_wrapper(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#[unsafe(export_name = #c_name)]
|
#[unsafe(export_name = #c_name)]
|
||||||
unsafe extern "C" fn #rust_name(#(#params),*) -> #ret {
|
unsafe extern "C" fn #rust_name(#(#params),*) -> #ret { unsafe { #call } }
|
||||||
unsafe { #call }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,6 +245,11 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
let mut params = vec![];
|
let mut params = vec![];
|
||||||
let mut register = vec![];
|
let mut register = vec![];
|
||||||
|
|
||||||
|
// for __new metamethods, ignore the first argument (ctype of self)
|
||||||
|
if func.attrs.metatable.as_deref() == Some("new") {
|
||||||
|
register.push(quote! { b.param_ignored(); });
|
||||||
|
}
|
||||||
|
|
||||||
for param in func.params.iter() {
|
for param in func.params.iter() {
|
||||||
let name = format!("{}", pat_ident(¶m.pat)?);
|
let name = format!("{}", pat_ident(¶m.pat)?);
|
||||||
let ty = ¶m.ty;
|
let ty = ¶m.ty;
|
||||||
@ -255,8 +271,10 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
quote! { #ffi::FfiReturnConvention::ByValue }
|
quote! { #ffi::FfiReturnConvention::ByValue }
|
||||||
};
|
};
|
||||||
|
|
||||||
let declare = quote! {
|
let declare = if func.ret_by_out {
|
||||||
b.declare::<unsafe extern "C" fn(#(#params),*) -> #ret>(#c_name);
|
quote! { b.declare::<unsafe extern "C" fn(*mut #ret, #(#params),*)>(#c_name); }
|
||||||
|
} else {
|
||||||
|
quote! { b.declare::<unsafe extern "C" fn(#(#params),*) -> #ret>(#c_name); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let register = match func.attrs.metatable {
|
let register = match func.attrs.metatable {
|
||||||
@ -274,10 +292,7 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! { #declare #register })
|
||||||
#declare
|
|
||||||
#register
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_ffi_exports<'a>(
|
fn generate_ffi_exports<'a>(
|
||||||
|
@ -136,7 +136,7 @@ fn init_vm(_args: &Args) -> luajit::State {
|
|||||||
luajit::State::new().unwrap_or_else(|err| panic!("failed to initialise runtime: {err}"));
|
luajit::State::new().unwrap_or_else(|err| panic!("failed to initialise runtime: {err}"));
|
||||||
|
|
||||||
let mut registry = luaffi::Registry::new();
|
let mut registry = luaffi::Registry::new();
|
||||||
registry.include::<lb_core::lb_core>();
|
registry.preload::<lb_core::lb_core>("lb:core");
|
||||||
|
|
||||||
println!("{registry}");
|
println!("{registry}");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user