Add ctype new support
This commit is contained in:
@@ -44,6 +44,17 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
||||
.map(generate_ffi_register)
|
||||
.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_cname = format!("{ty_name}_drop");
|
||||
|
||||
@@ -78,6 +89,8 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
||||
#(#ffi_register)*
|
||||
#(#lua_register)*
|
||||
|
||||
#ffi_new_fallback
|
||||
|
||||
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_cname);
|
||||
b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname));
|
||||
}
|
||||
@@ -100,7 +113,7 @@ struct FfiFunction {
|
||||
|
||||
#[derive(Default)]
|
||||
struct FfiFunctionAttrs {
|
||||
metatable: Option<LitStr>,
|
||||
metatable: Option<String>,
|
||||
}
|
||||
|
||||
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) {
|
||||
if let Some(name) = attr.path().get_ident() {
|
||||
if name == "metatable" {
|
||||
parsed.metatable = attr.parse_args()?;
|
||||
parsed.metatable = Some(attr.parse_args::<LitStr>()?.value());
|
||||
attrs.remove(i);
|
||||
continue;
|
||||
} else if name == "new" {
|
||||
parsed.metatable = parse_quote!("new");
|
||||
parsed.metatable = Some("new".into());
|
||||
attrs.remove(i);
|
||||
continue;
|
||||
}
|
||||
@@ -194,7 +207,7 @@ fn generate_ffi_wrapper(func: &FfiFunction) -> Result<TokenStream> {
|
||||
let mut args = vec![];
|
||||
|
||||
for (i, param) in func.params.iter().enumerate() {
|
||||
let name = format_ident!("__arg{i}");
|
||||
let name = format_ident!("arg{i}");
|
||||
let ty = ¶m.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 {
|
||||
// make return by out-param the first parameter
|
||||
let ret = &func.ret;
|
||||
params.insert(0, quote! { __out: *mut #ret });
|
||||
params.insert(0, quote! { out: *mut #ret });
|
||||
(
|
||||
quote!(()),
|
||||
quote! { ::std::ptr::write(__out, Self::#name(#(#args),*)) },
|
||||
quote! { ::std::ptr::write(out, Self::#name(#(#args),*)) },
|
||||
)
|
||||
} else {
|
||||
let ret = &func.ret;
|
||||
@@ -220,9 +233,7 @@ fn generate_ffi_wrapper(func: &FfiFunction) -> Result<TokenStream> {
|
||||
|
||||
Ok(quote! {
|
||||
#[unsafe(export_name = #c_name)]
|
||||
unsafe extern "C" fn #rust_name(#(#params),*) -> #ret {
|
||||
unsafe { #call }
|
||||
}
|
||||
unsafe extern "C" fn #rust_name(#(#params),*) -> #ret { unsafe { #call } }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -234,6 +245,11 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
||||
let mut params = 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() {
|
||||
let name = format!("{}", pat_ident(¶m.pat)?);
|
||||
let ty = ¶m.ty;
|
||||
@@ -255,8 +271,10 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
||||
quote! { #ffi::FfiReturnConvention::ByValue }
|
||||
};
|
||||
|
||||
let declare = quote! {
|
||||
b.declare::<unsafe extern "C" fn(#(#params),*) -> #ret>(#c_name);
|
||||
let declare = if func.ret_by_out {
|
||||
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 {
|
||||
@@ -274,10 +292,7 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
||||
},
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
#declare
|
||||
#register
|
||||
})
|
||||
Ok(quote! { #declare #register })
|
||||
}
|
||||
|
||||
fn generate_ffi_exports<'a>(
|
||||
|
||||
Reference in New Issue
Block a user