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
}
/// 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 != "()" {
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();
}
/// 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();
}
/// 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();
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() {
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();
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");
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);
}
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
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() {
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() {
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"
}
/// 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,