From 1149f7a5a5fc9dab46d6081d2011ef07e9223c85 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 5 Jan 2021 14:02:02 -0500 Subject: [PATCH] [bindings] Allow manual setting of struct/enum attributes --- c-bindings-gen/src/blocks.rs | 13 +++++++------ c-bindings-gen/src/main.rs | 15 ++++++++++----- c-bindings-gen/src/types.rs | 6 +++--- genbindings.sh | 2 +- lightning-c-bindings/src/chain/chaininterface.rs | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/c-bindings-gen/src/blocks.rs b/c-bindings-gen/src/blocks.rs index e9aca1140..3bad3e305 100644 --- a/c-bindings-gen/src/blocks.rs +++ b/c-bindings-gen/src/blocks.rs @@ -5,6 +5,7 @@ use std::fs::File; use std::io::Write; use proc_macro2::{TokenTree, Span}; +use crate::GlobalOpts; use crate::types::*; /// Writes out a C++ wrapper class for the given type, which contains various utilities to access @@ -33,7 +34,7 @@ pub fn write_cpp_wrapper(cpp_header_file: &mut File, ty: &str, has_destructor: b } /// Writes out a C-callable concrete Result struct and utility methods -pub fn write_result_block(w: &mut W, mangled_container: &str, ok_type: &str, err_type: &str) { +pub fn write_result_block(w: &mut W, opts: &GlobalOpts, mangled_container: &str, ok_type: &str, err_type: &str) { writeln!(w, "#[repr(C)]").unwrap(); writeln!(w, "pub union {}Ptr {{", mangled_container).unwrap(); if ok_type != "()" { @@ -49,7 +50,7 @@ pub fn write_result_block(w: &mut W, mangled_container: &str, writeln!(w, "\tpub err: *mut std::ffi::c_void,").unwrap(); } writeln!(w, "}}").unwrap(); - writeln!(w, "#[repr(C)]").unwrap(); + writeln!(w, "{}", opts.struct_attributes).unwrap(); writeln!(w, "pub struct {} {{", mangled_container).unwrap(); writeln!(w, "\tpub contents: {}Ptr,", mangled_container).unwrap(); writeln!(w, "\tpub result_ok: bool,").unwrap(); @@ -147,8 +148,8 @@ pub fn write_result_block(w: &mut W, mangled_container: &str, } /// Writes out a C-callable concrete Vec struct and utility methods -pub fn write_vec_block(w: &mut W, mangled_container: &str, inner_type: &str) { - writeln!(w, "#[repr(C)]").unwrap(); +pub fn write_vec_block(w: &mut W, opts: &GlobalOpts, mangled_container: &str, inner_type: &str) { + writeln!(w, "{}", opts.struct_attributes).unwrap(); writeln!(w, "pub struct {} {{", mangled_container).unwrap(); writeln!(w, "\tpub data: *mut {},", inner_type).unwrap(); writeln!(w, "\tpub datalen: usize").unwrap(); @@ -196,8 +197,8 @@ pub fn write_vec_block(w: &mut W, mangled_container: &str, in } /// Writes out a C-callable concrete (A, B, ...) struct and utility methods -pub fn write_tuple_block(w: &mut W, mangled_container: &str, types: &[String]) { - writeln!(w, "#[repr(C)]").unwrap(); +pub fn write_tuple_block(w: &mut W, opts: &GlobalOpts, mangled_container: &str, types: &[String]) { + writeln!(w, "{}", opts.struct_attributes).unwrap(); writeln!(w, "pub struct {} {{", mangled_container).unwrap(); for (idx, ty) in types.iter().enumerate() { writeln!(w, "\tpub {}: {},", ('a' as u8 + idx as u8) as char, ty).unwrap(); diff --git a/c-bindings-gen/src/main.rs b/c-bindings-gen/src/main.rs index a32b9d0c5..ba605bd72 100644 --- a/c-bindings-gen/src/main.rs +++ b/c-bindings-gen/src/main.rs @@ -269,7 +269,8 @@ fn writeln_trait<'a, 'b, W: std::io::Write>(w: &mut W, t: &'a syn::ItemTrait, ty assert!(gen_types.learn_generics(&t.generics, types)); gen_types.learn_associated_types(&t, types); - writeln!(w, "#[repr(C)]\npub struct {} {{", trait_name).unwrap(); + writeln!(w, "{}", types.opts.struct_attributes).unwrap(); + writeln!(w, "pub struct {} {{", trait_name).unwrap(); writeln!(w, "\tpub this_arg: *mut c_void,").unwrap(); let mut generated_fields = Vec::new(); // Every field's name except this_arg, used in Clone generation for item in t.items.iter() { @@ -530,7 +531,8 @@ fn writeln_opaque(w: &mut W, ident: &syn::Ident, struct_name: writeln!(w, ";\n").unwrap(); writeln!(extra_headers, "struct native{}Opaque;\ntypedef struct native{}Opaque LDKnative{};", ident, ident, ident).unwrap(); writeln_docs(w, &attrs, ""); - writeln!(w, "#[must_use]\n#[repr(C)]\npub struct {} {{\n\t/// Nearly everywhere, inner must be non-null, however in places where", struct_name).unwrap(); + writeln!(w, "{}", types.opts.struct_attributes).unwrap(); + writeln!(w, "#[must_use]\npub struct {} {{\n\t/// Nearly everywhere, inner must be non-null, however in places where", struct_name).unwrap(); writeln!(w, "\t/// the Rust equivalent takes an Option, it may be set to null to indicate None.").unwrap(); writeln!(w, "\tpub inner: *mut native{},\n\tpub is_owned: bool,\n}}\n", ident).unwrap(); writeln!(w, "impl Drop for {} {{\n\tfn drop(&mut self) {{", struct_name).unwrap(); @@ -1082,7 +1084,8 @@ fn writeln_enum<'a, 'b, W: std::io::Write>(w: &mut W, e: &'a syn::ItemEnum, type let mut needs_free = false; - writeln!(w, "#[must_use]\n#[derive(Clone)]\n#[repr(C)]\npub enum {} {{", e.ident).unwrap(); + writeln!(w, "{}", types.opts.struct_attributes).unwrap(); + writeln!(w, "#[must_use]\n#[derive(Clone)]\npub enum {} {{", e.ident).unwrap(); for var in e.variants.iter() { assert_eq!(export_status(&var.attrs), ExportStatus::Export); // We can't partially-export a mirrored enum writeln_docs(w, &var.attrs, "\t"); @@ -1554,12 +1557,13 @@ fn walk_ast<'a>(in_dir: &str, path: &str, module: String, ast_storage: &'a FullL pub struct GlobalOpts<'a> { orig_crate: &'a str, fn_attributes: &'a str, + struct_attributes: &'a str, } fn main() { let args: Vec = env::args().collect(); - if args.len() != 8 { - eprintln!("Usage: source/dir target/dir source_crate_name derived_templates.rs extra/includes.h extra/cpp/includes.hpp fn_attribute"); + if args.len() != 9 { + eprintln!("Usage: source/dir target/dir source_crate_name derived_templates.rs extra/includes.h extra/cpp/includes.hpp fn_attribute struct_attribute"); process::exit(1); } @@ -1587,6 +1591,7 @@ fn main() { let opts = GlobalOpts { orig_crate: &args[3], fn_attributes: &args[7], + struct_attributes: &args[8], }; // First parse the full crate's ASTs, caching them so that we can hold references to the AST diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 9084918fc..2ecfc839d 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -1805,11 +1805,11 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { self.write_template_generics(&mut b_ty, &mut args.iter().map(|t| *t).skip(1), generics, is_ref); } - write_result_block(&mut created_container, &mangled_container, &String::from_utf8(a_ty).unwrap(), &String::from_utf8(b_ty).unwrap()); + write_result_block(&mut created_container, &self.opts, &mangled_container, &String::from_utf8(a_ty).unwrap(), &String::from_utf8(b_ty).unwrap()); } else if container_type == "Vec" { let mut a_ty: Vec = Vec::new(); self.write_template_generics(&mut a_ty, &mut args.iter().map(|t| *t), generics, is_ref); - write_vec_block(&mut created_container, &mangled_container, &String::from_utf8(a_ty).unwrap()); + write_vec_block(&mut created_container, &self.opts, &mangled_container, &String::from_utf8(a_ty).unwrap()); } else if container_type.ends_with("Tuple") { let mut tuple_args = Vec::new(); for arg in args.iter() { @@ -1817,7 +1817,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { self.write_template_generics(&mut ty, &mut [arg].iter().map(|t| **t), generics, is_ref); tuple_args.push(String::from_utf8(ty).unwrap()); } - write_tuple_block(&mut created_container, &mangled_container, &tuple_args); + write_tuple_block(&mut created_container, &self.opts, &mangled_container, &tuple_args); write!(&mut created_container, "{}\npub extern \"C\" fn {}_new(", self.opts.fn_attributes, mangled_container).unwrap(); for (idx, gen) in args.iter().enumerate() { diff --git a/genbindings.sh b/genbindings.sh index bf04c513c..da8a1c15a 100755 --- a/genbindings.sh +++ b/genbindings.sh @@ -25,7 +25,7 @@ OUT="$(pwd)/lightning-c-bindings/src" OUT_TEMPL="$(pwd)/lightning-c-bindings/src/c_types/derived.rs" OUT_F="$(pwd)/lightning-c-bindings/include/rust_types.h" OUT_CPP="$(pwd)/lightning-c-bindings/include/lightningpp.hpp" -RUST_BACKTRACE=1 ./c-bindings-gen/target/debug/c-bindings-gen $SRC/ $OUT/ lightning $OUT_TEMPL $OUT_F $OUT_CPP "#[no_mangle]" +RUST_BACKTRACE=1 ./c-bindings-gen/target/debug/c-bindings-gen $SRC/ $OUT/ lightning $OUT_TEMPL $OUT_F $OUT_CPP "#[no_mangle]" "#[repr(C)]" # Now cd to lightning-c-bindings, build the generated bindings, and call cbindgen to build a C header file PATH="$PATH:~/.cargo/bin" diff --git a/lightning-c-bindings/src/chain/chaininterface.rs b/lightning-c-bindings/src/chain/chaininterface.rs index b5f510323..48d8f29e9 100644 --- a/lightning-c-bindings/src/chain/chaininterface.rs +++ b/lightning-c-bindings/src/chain/chaininterface.rs @@ -47,9 +47,9 @@ impl Drop for BroadcasterInterface { } /// An enum that represents the speed at which we want a transaction to confirm used for feerate /// estimation. +#[repr(C)] #[must_use] #[derive(Clone)] -#[repr(C)] pub enum ConfirmationTarget { /// We are happy with this transaction confirming slowly when feerate drops some. Background, -- 2.39.5