diff --git a/crates/luaffi_impl/src/cdef.rs b/crates/luaffi_impl/src/cdef.rs index c763f4d..cad0111 100644 --- a/crates/luaffi_impl/src/cdef.rs +++ b/crates/luaffi_impl/src/cdef.rs @@ -2,7 +2,7 @@ use crate::utils::{ffi_crate, syn_assert, syn_error}; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::*; +use syn::{ext::IdentExt, *}; #[derive(Debug, FromMeta)] pub struct Args {} @@ -42,8 +42,8 @@ pub fn transform(_args: Args, mut item: Item) -> Result { fn generate_type(ty: &Ident) -> Result { let ffi = ffi_crate(); let fmt = quote!(::std::format!); - let name = LitStr::new(&format!("{ty}"), ty.span()); - let cdecl_fmt = LitStr::new(&format!("struct {ty} {{}}"), ty.span()); + let name = LitStr::new(&format!("{}", ty.unraw()), ty.span()); + let cdecl_fmt = LitStr::new(&format!("struct {} {{}}", ty.unraw()), ty.span()); Ok(quote! { unsafe impl #ffi::Type for #ty { @@ -79,8 +79,8 @@ fn generate_cdef_structure(str: &mut ItemStruct) -> Result { let build = generate_build_cdef(&to_cfields(&mut str.fields)?)?; Ok(quote! { - unsafe impl #ffi::CDef for #ty { - fn build(b: &mut #ffi::CDefBuilder) { #build } + unsafe impl #ffi::Cdef for #ty { + fn build(b: &mut #ffi::CdefBuilder) { #build } } }) } @@ -104,8 +104,8 @@ fn generate_cdef_enum(enu: &mut ItemEnum) -> Result { .collect::>>()?; Ok(quote! { - unsafe impl #ffi::CDef for #ty { - fn build(b: &mut #ffi::CDefBuilder) { + unsafe impl #ffi::Cdef for #ty { + fn build(b: &mut #ffi::CdefBuilder) { b.field::<::std::ffi::c_int>("__tag").inner_union(|b| { #(#build)* }); } } @@ -133,7 +133,7 @@ fn to_cfields(fields: &mut Fields) -> Result> { .map(|(i, field)| { Ok(CField { name: match field.ident { - Some(ref name) => format!("{name}"), + Some(ref name) => format!("{}", name.unraw()), None => format!("__{i}"), }, ty: field.ty.clone(), diff --git a/crates/luaffi_impl/src/metatype.rs b/crates/luaffi_impl/src/metatype.rs index 95d4e48..1efcc16 100644 --- a/crates/luaffi_impl/src/metatype.rs +++ b/crates/luaffi_impl/src/metatype.rs @@ -1,7 +1,7 @@ use crate::utils::{ffi_crate, is_primitive, is_unit, pat_ident, syn_assert, ty_name}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::*; +use syn::{ext::IdentExt, *}; pub fn transform(mut imp: ItemImpl) -> Result { syn_assert!( @@ -44,12 +44,13 @@ fn generate_impls(imp: &mut ItemImpl) -> Result { .map(generate_ffi_register) .collect::>()?; - let ffi_new_fallback = match ffi_funcs + let ffi_register_new = match ffi_funcs .iter() .find(|f| f.attrs.metatable.as_deref() == Some("new")) { Some(_) => None, None => Some({ + // fallback error constructor to prevent creating uninitialised ctypes let err = format!(r#"function() error("type '{ty_name}' has no constructor"); end"#); quote! { b.metatable_raw("new", #err); } }), @@ -57,6 +58,19 @@ fn generate_impls(imp: &mut ItemImpl) -> Result { let ffi_drop_rname = format_ident!("__ffi_drop"); let ffi_drop_cname = format!("{ty_name}_drop"); + let ffi_wrapper_drop = quote! { + #[unsafe(export_name = #ffi_drop_cname)] + unsafe extern "C" fn #ffi_drop_rname(ptr: *mut Self) { + unsafe { ::std::ptr::drop_in_place(ptr) } + } + }; + + let ffi_register_drop = quote! { + if ::std::mem::needs_drop::() { + b.declare::(#ffi_drop_cname); + b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname)); + } + }; // ffi function symbol export code let ffi_exports = { @@ -75,11 +89,7 @@ fn generate_impls(imp: &mut ItemImpl) -> Result { Ok(quote! { impl #ty { #(#ffi_wrappers)* - - #[unsafe(export_name = #ffi_drop_cname)] - unsafe extern "C" fn #ffi_drop_rname(ptr: *mut Self) { - unsafe { ::std::ptr::drop_in_place(ptr) } - } + #ffi_wrapper_drop } unsafe impl #ffi::Metatype for #ty { @@ -89,10 +99,8 @@ fn generate_impls(imp: &mut ItemImpl) -> Result { #(#ffi_register)* #(#lua_register)* - #ffi_new_fallback - - b.declare::(#ffi_drop_cname); - b.metatable_raw("gc", ::std::format_args!("__C.{}", #ffi_drop_cname)); + #ffi_register_new + #ffi_register_drop } } @@ -154,9 +162,9 @@ fn get_ffi_functions(imp: &mut ItemImpl) -> Result> { funcs.push(FfiFunction { name: func.sig.ident.clone(), - rust_name: format_ident!("__ffi_{}", func.sig.ident), - lua_name: format!("{}", func.sig.ident), - c_name: format!("{}_{}", ty_name(&imp.self_ty)?, func.sig.ident), + rust_name: format_ident!("__ffi_{}", func.sig.ident.unraw()), + lua_name: format!("{}", func.sig.ident.unraw()), + c_name: format!("{}_{}", ty_name(&imp.self_ty)?, func.sig.ident.unraw()), params, ret, ret_by_out, @@ -311,7 +319,7 @@ fn generate_ffi_exports<'a>( struct LuaFunction { name: String, - params: Vec, + params: Vec, body: Block, } @@ -325,8 +333,8 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result> { && let Some(ref abi) = abi.name && abi.value() == "Lua" { - // normalise inputs to PatType - let params = func + // normalise inputs to Pat + let mut params: Vec<_> = func .sig .inputs .iter() @@ -337,11 +345,15 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result> { syn_assert!(recv.mutability.is_none(), recv, "cannot be mut"); parse_quote! { self: cdata } } - FnArg::Typed(ty) => ty.clone(), + FnArg::Typed(ty) => Pat::Type(ty.clone()), }) }) .collect::>()?; + if let Some(_) = func.sig.variadic { + params.push(parse_quote!(variadic!())); + } + // shouldn't specify an output type syn_assert!( matches!(func.sig.output, ReturnType::Default), @@ -350,7 +362,7 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result> { ); funcs.push(LuaFunction { - name: format!("{}", func.sig.ident), + name: format!("{}", func.sig.ident.unraw()), body: func.block.clone(), params, });