[bindings] Allow manual setting of struct/enum attributes
authorMatt Corallo <git@bluematt.me>
Tue, 5 Jan 2021 19:02:02 +0000 (14:02 -0500)
committerMatt Corallo <git@bluematt.me>
Tue, 5 Jan 2021 19:02:02 +0000 (14:02 -0500)
c-bindings-gen/src/blocks.rs
c-bindings-gen/src/main.rs
c-bindings-gen/src/types.rs
genbindings.sh
lightning-c-bindings/src/chain/chaininterface.rs

index e9aca1140d4c2c17935f7b5b291bb16aade25d76..3bad3e30551c64d6138a8f387bb285f656b10a05 100644 (file)
@@ -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<A, B> struct and utility methods
-pub fn write_result_block<W: std::io::Write>(w: &mut W, mangled_container: &str, ok_type: &str, err_type: &str) {
+pub fn write_result_block<W: std::io::Write>(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: std::io::Write>(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: std::io::Write>(w: &mut W, mangled_container: &str,
 }
 
 /// Writes out a C-callable concrete Vec<A> struct and utility methods
-pub fn write_vec_block<W: std::io::Write>(w: &mut W, mangled_container: &str, inner_type: &str) {
-       writeln!(w, "#[repr(C)]").unwrap();
+pub fn write_vec_block<W: std::io::Write>(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: std::io::Write>(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: std::io::Write>(w: &mut W, mangled_container: &str, types: &[String]) {
-       writeln!(w, "#[repr(C)]").unwrap();
+pub fn write_tuple_block<W: std::io::Write>(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();
index a32b9d0c5df24b29d064dc99a3fac5f411cff35e..ba605bd72d4dc05c8fdfbb939bcdc68765836fe6 100644 (file)
@@ -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: std::io::Write>(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<String> = 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
index 9084918fcb5f9e89b8cf229c93f1c43ecf57a48f..2ecfc839d16fc9e1111c55b535d06566bfc8f27c 100644 (file)
@@ -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<u8> = 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() {
index bf04c513cdfbccab1a0ceff096ce9be2344d9a8d..da8a1c15a5c06e9fd1b39772eb9899e5fe0cc0d2 100755 (executable)
@@ -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"
index b5f51032326edc1cac5ae8b0e763c4d4e9b82082..48d8f29e92efff22ea9e986f00237527b3bd1088 100644 (file)
@@ -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,