Automatically generate drop for #[metatype]
This commit is contained in:
parent
8f6fc64f7a
commit
f9676a1436
@ -7,6 +7,7 @@ edition = "2024"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
darling = "0.20.11"
|
||||
proc-macro2 = "1.0.95"
|
||||
quote = "1.0.40"
|
||||
syn = { version = "2.0.103", features = ["full", "visit-mut"] }
|
||||
|
@ -1,9 +1,15 @@
|
||||
use crate::utils::{ffi_crate, syn_assert, syn_error};
|
||||
use darling::FromMeta;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{spanned::*, *};
|
||||
|
||||
pub fn transform(mut item: Item) -> Result<TokenStream> {
|
||||
#[derive(Debug, FromMeta)]
|
||||
pub struct Args {
|
||||
module: Option<String>,
|
||||
}
|
||||
|
||||
pub fn transform(args: Args, mut item: Item) -> Result<TokenStream> {
|
||||
let (name, impl_type, impl_cdef) = match item {
|
||||
Item::Struct(ref mut str) => (
|
||||
str.ident.clone(),
|
||||
|
@ -1,3 +1,4 @@
|
||||
use darling::{FromMeta, ast::NestedMeta};
|
||||
use proc_macro::TokenStream as TokenStream1;
|
||||
use quote::ToTokens;
|
||||
use syn::parse_macro_input;
|
||||
@ -8,7 +9,9 @@ mod utils;
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn cdef(args: TokenStream1, input: TokenStream1) -> TokenStream1 {
|
||||
cdef::transform(parse_macro_input!(input))
|
||||
NestedMeta::parse_meta_list(args.into())
|
||||
.and_then(|meta| cdef::Args::from_list(&meta).map_err(Into::into))
|
||||
.and_then(|args| cdef::transform(args, syn::parse(input)?))
|
||||
.unwrap_or_else(|err| err.into_compile_error().into_token_stream())
|
||||
.into()
|
||||
}
|
||||
|
@ -26,25 +26,36 @@ pub fn transform(mut imp: ItemImpl) -> Result<TokenStream> {
|
||||
}
|
||||
|
||||
fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
||||
let ty = imp.self_ty.clone();
|
||||
let ty_name = ty_name(&ty)?;
|
||||
|
||||
let ffi = ffi_crate();
|
||||
let ffi_funcs = get_ffi_functions(imp)?;
|
||||
let ffi_wrappers: Vec<_> = ffi_funcs
|
||||
.iter()
|
||||
.map(generate_ffi_wrapper)
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
let ffi_register: Vec<_> = ffi_funcs
|
||||
.iter()
|
||||
.map(generate_ffi_register)
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
let ffi_drop_fn = format_ident!("__ffi_drop");
|
||||
let ffi_drop_name = format!("{ty_name}_drop");
|
||||
|
||||
let ffi_exports = {
|
||||
let mut names = vec![&ffi_drop_fn];
|
||||
names.extend(ffi_funcs.iter().map(|f| &f.rust_name));
|
||||
generate_ffi_exports(&ty, names.into_iter())?
|
||||
};
|
||||
|
||||
let lua_funcs = get_lua_functions(imp)?;
|
||||
let lua_register: Vec<_> = lua_funcs
|
||||
.iter()
|
||||
.map(generate_lua_register)
|
||||
.collect::<Result<_>>()?;
|
||||
|
||||
let ty = &*imp.self_ty;
|
||||
|
||||
Ok(quote! {
|
||||
unsafe impl #ffi::Metatype for #ty {
|
||||
type Target = Self;
|
||||
@ -52,10 +63,22 @@ fn generate_impls(imp: &mut ItemImpl) -> Result<TokenStream> {
|
||||
fn build(b: &mut #ffi::MetatypeBuilder) {
|
||||
#(#ffi_register)*
|
||||
#(#lua_register)*
|
||||
|
||||
b.declare::<unsafe extern "C" fn(*mut Self)>(#ffi_drop_name);
|
||||
b.metatable_raw("gc", ::std::format_args!("C.{}", #ffi_drop_name));
|
||||
}
|
||||
}
|
||||
|
||||
impl #ty { #(#ffi_wrappers)* }
|
||||
impl #ty {
|
||||
#(#ffi_wrappers)*
|
||||
|
||||
#[unsafe(export_name = #ffi_drop_name)]
|
||||
unsafe extern "C" fn #ffi_drop_fn(&mut self) {
|
||||
unsafe { ::std::ptr::drop_in_place(self) }
|
||||
}
|
||||
}
|
||||
|
||||
#ffi_exports
|
||||
})
|
||||
}
|
||||
|
||||
@ -213,6 +236,19 @@ fn generate_ffi_register(func: &FfiFunction) -> Result<TokenStream> {
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_ffi_exports<'a>(
|
||||
ty: &Type,
|
||||
names: impl Iterator<Item = &'a Ident>,
|
||||
) -> Result<TokenStream> {
|
||||
Ok(quote! {
|
||||
// hack to prevent ffi functions from being dead code-eliminated
|
||||
#[used]
|
||||
static __FFI_EXPORTS: &[fn()] = unsafe {
|
||||
&[#(::std::mem::transmute(#ty::#names as *const ())),*]
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
struct LuaFunction {
|
||||
name: String,
|
||||
params: Vec<PatType>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user