diff --git a/docs.md b/docs.md index 725e31af..4b0c68a6 100644 --- a/docs.md +++ b/docs.md @@ -488,7 +488,16 @@ renaming_overrides_prefixing = true "MyType" = "my_cool_type" "my_function" = "BetterFunctionName" -# Table of things to add to the body of any struct, union, or enum that has the +# Table of things to prepend to the body of any struct, union, or enum that has the +# given name. This can be used to add things like methods which don't change ABI, +# mark fields private, etc +[export.pre_body] +"MyType" = """ + MyType() = delete; +private: +""" + +# Table of things to append to the body of any struct, union, or enum that has the # given name. This can be used to add things like methods which don't change ABI. [export.body] "MyType" = """ diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 620963af..0c3834ef 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -214,6 +214,8 @@ pub struct ExportConfig { pub exclude: Vec, /// Table of name conversions to apply to item names pub rename: HashMap, + /// Table of raw strings to prepend to the body of items. + pub pre_body: HashMap, /// Table of raw strings to append to the body of items. pub body: HashMap, /// A prefix to add before the name of every item @@ -229,7 +231,11 @@ impl ExportConfig { self.item_types.is_empty() || self.item_types.contains(&item_type) } - pub(crate) fn extra_body(&self, path: &Path) -> Option<&str> { + pub(crate) fn pre_body(&self, path: &Path) -> Option<&str> { + self.pre_body.get(path.name()).map(|s| s.trim_matches('\n')) + } + + pub(crate) fn post_body(&self, path: &Path) -> Option<&str> { self.body.get(path.name()).map(|s| s.trim_matches('\n')) } diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index 8592d5f2..9451feda 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -527,6 +527,14 @@ impl Source for Enum { write!(out, " {}", self.export_name()); out.open_brace(); + + // Emit the pre_body section, if relevant + // Only do this here if we're writing C++, since the struct that wraps everything is starting here. + // If we're writing C, we aren't wrapping the enum and variant structs definitions, so the actual enum struct willstart down below + if let Some(body) = config.export.pre_body(&self.path) { + out.write_raw_block(body); + out.new_line(); + } } let enum_name = if let Some(ref tag) = self.tag { @@ -642,6 +650,14 @@ impl Source for Enum { } out.open_brace(); + + // Emit the pre_body section, if relevant + // Only do this if we're writing C, since the struct is starting right here. + // For C++, the struct wraps all of the above variant structs too, and we write the pre_body section at the begining of that + if let Some(body) = config.export.pre_body(&self.path) { + out.write_raw_block(body); + out.new_line(); + } } // C++ allows accessing only common initial sequence of union @@ -1008,7 +1024,9 @@ impl Source for Enum { } } - if let Some(body) = config.export.extra_body(&self.path) { + // Emit the post_body section, if relevant + if let Some(body) = config.export.post_body(&self.path) { + out.new_line(); out.write_raw_block(body); } diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index cd508053..946f41cf 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -452,6 +452,12 @@ impl Source for Struct { out.open_brace(); + // Emit the pre_body section, if relevant + if let Some(body) = config.export.pre_body(&self.path) { + out.write_raw_block(body); + out.new_line(); + } + if config.documentation { out.write_vertical_source_list(&self.fields, ListType::Cap(";")); } else { @@ -600,7 +606,9 @@ impl Source for Struct { } } - if let Some(body) = config.export.extra_body(&self.path) { + // Emit the post_body section, if relevant + if let Some(body) = config.export.post_body(&self.path) { + out.new_line(); out.write_raw_block(body); } diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index afb4cf0b..96a0a861 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -299,6 +299,12 @@ impl Source for Union { out.open_brace(); + // Emit the pre_body section, if relevant + if let Some(body) = config.export.pre_body(&self.path) { + out.write_raw_block(body); + out.new_line(); + } + if config.documentation { out.write_vertical_source_list(&self.fields, ListType::Cap(";")); } else { @@ -310,7 +316,9 @@ impl Source for Union { out.write_vertical_source_list(&vec[..], ListType::Cap(";")); } - if let Some(body) = config.export.extra_body(&self.path) { + // Emit the post_body section, if relevant + if let Some(body) = config.export.post_body(&self.path) { + out.new_line(); out.write_raw_block(body); } diff --git a/src/bindgen/writer.rs b/src/bindgen/writer.rs index 1fdb0a0e..78218586 100644 --- a/src/bindgen/writer.rs +++ b/src/bindgen/writer.rs @@ -176,7 +176,6 @@ impl<'a, F: Write> SourceWriter<'a, F> { } pub fn write_raw_block(&mut self, block: &str) { - self.new_line(); self.line_started = true; write!(self, "{}", block); } diff --git a/tests/expectations/body.c b/tests/expectations/body.c index e0cb7c13..4dc55062 100644 --- a/tests/expectations/body.c +++ b/tests/expectations/body.c @@ -9,6 +9,12 @@ typedef enum { Baz1, } MyCLikeEnum; +typedef enum { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +} MyCLikeEnum_Prepended; + typedef struct { int32_t i; #ifdef __cplusplus @@ -47,4 +53,49 @@ typedef union { int32_t extra_member; // yolo } MyUnion; -void root(MyFancyStruct s, MyFancyEnum e, MyCLikeEnum c, MyUnion u); +typedef struct { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +} MyFancyStruct_Prepended; + +typedef enum { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +} MyFancyEnum_Prepended_Tag; + +typedef struct { + int32_t _0; +} Bar_Prepended_Body; + +typedef struct { + int32_t _0; +} Baz_Prepended_Body; + +typedef struct { + #ifdef __cplusplus + inline void wohoo(); + #endif + MyFancyEnum_Prepended_Tag tag; + union { + Bar_Prepended_Body bar_prepended; + Baz_Prepended_Body baz_prepended; + }; +} MyFancyEnum_Prepended; + +typedef union { + int32_t extra_member; // yolo + float f; + uint32_t u; +} MyUnion_Prepended; + +void root(MyFancyStruct s, + MyFancyEnum e, + MyCLikeEnum c, + MyUnion u, + MyFancyStruct_Prepended sp, + MyFancyEnum_Prepended ep, + MyCLikeEnum_Prepended cp, + MyUnion_Prepended up); diff --git a/tests/expectations/body.compat.c b/tests/expectations/body.compat.c index 6ae82cfb..3db7c7ee 100644 --- a/tests/expectations/body.compat.c +++ b/tests/expectations/body.compat.c @@ -9,6 +9,12 @@ typedef enum { Baz1, } MyCLikeEnum; +typedef enum { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +} MyCLikeEnum_Prepended; + typedef struct { int32_t i; #ifdef __cplusplus @@ -47,11 +53,56 @@ typedef union { int32_t extra_member; // yolo } MyUnion; +typedef struct { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +} MyFancyStruct_Prepended; + +typedef enum { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +} MyFancyEnum_Prepended_Tag; + +typedef struct { + int32_t _0; +} Bar_Prepended_Body; + +typedef struct { + int32_t _0; +} Baz_Prepended_Body; + +typedef struct { + #ifdef __cplusplus + inline void wohoo(); + #endif + MyFancyEnum_Prepended_Tag tag; + union { + Bar_Prepended_Body bar_prepended; + Baz_Prepended_Body baz_prepended; + }; +} MyFancyEnum_Prepended; + +typedef union { + int32_t extra_member; // yolo + float f; + uint32_t u; +} MyUnion_Prepended; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(MyFancyStruct s, MyFancyEnum e, MyCLikeEnum c, MyUnion u); +void root(MyFancyStruct s, + MyFancyEnum e, + MyCLikeEnum c, + MyUnion u, + MyFancyStruct_Prepended sp, + MyFancyEnum_Prepended ep, + MyCLikeEnum_Prepended cp, + MyUnion_Prepended up); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/body.cpp b/tests/expectations/body.cpp index bce30ce3..8fbc524c 100644 --- a/tests/expectations/body.cpp +++ b/tests/expectations/body.cpp @@ -9,6 +9,12 @@ enum class MyCLikeEnum { Baz1, }; +enum class MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +}; + struct MyFancyStruct { int32_t i; #ifdef __cplusplus @@ -47,8 +53,53 @@ union MyUnion { int32_t extra_member; // yolo }; +struct MyFancyStruct_Prepended { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +}; + +struct MyFancyEnum_Prepended { + #ifdef __cplusplus + inline void wohoo(); + #endif + enum class Tag { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, + }; + + struct Bar_Prepended_Body { + int32_t _0; + }; + + struct Baz_Prepended_Body { + int32_t _0; + }; + + Tag tag; + union { + Bar_Prepended_Body bar_prepended; + Baz_Prepended_Body baz_prepended; + }; +}; + +union MyUnion_Prepended { + int32_t extra_member; // yolo + float f; + uint32_t u; +}; + extern "C" { -void root(MyFancyStruct s, MyFancyEnum e, MyCLikeEnum c, MyUnion u); +void root(MyFancyStruct s, + MyFancyEnum e, + MyCLikeEnum c, + MyUnion u, + MyFancyStruct_Prepended sp, + MyFancyEnum_Prepended ep, + MyCLikeEnum_Prepended cp, + MyUnion_Prepended up); } // extern "C" diff --git a/tests/expectations/both/body.c b/tests/expectations/both/body.c index 58e3c335..743422be 100644 --- a/tests/expectations/both/body.c +++ b/tests/expectations/both/body.c @@ -9,6 +9,12 @@ typedef enum MyCLikeEnum { Baz1, } MyCLikeEnum; +typedef enum MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +} MyCLikeEnum_Prepended; + typedef struct MyFancyStruct { int32_t i; #ifdef __cplusplus @@ -47,4 +53,49 @@ typedef union MyUnion { int32_t extra_member; // yolo } MyUnion; -void root(MyFancyStruct s, MyFancyEnum e, MyCLikeEnum c, MyUnion u); +typedef struct MyFancyStruct_Prepended { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +} MyFancyStruct_Prepended; + +typedef enum MyFancyEnum_Prepended_Tag { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +} MyFancyEnum_Prepended_Tag; + +typedef struct Bar_Prepended_Body { + int32_t _0; +} Bar_Prepended_Body; + +typedef struct Baz_Prepended_Body { + int32_t _0; +} Baz_Prepended_Body; + +typedef struct MyFancyEnum_Prepended { + #ifdef __cplusplus + inline void wohoo(); + #endif + MyFancyEnum_Prepended_Tag tag; + union { + Bar_Prepended_Body bar_prepended; + Baz_Prepended_Body baz_prepended; + }; +} MyFancyEnum_Prepended; + +typedef union MyUnion_Prepended { + int32_t extra_member; // yolo + float f; + uint32_t u; +} MyUnion_Prepended; + +void root(MyFancyStruct s, + MyFancyEnum e, + MyCLikeEnum c, + MyUnion u, + MyFancyStruct_Prepended sp, + MyFancyEnum_Prepended ep, + MyCLikeEnum_Prepended cp, + MyUnion_Prepended up); diff --git a/tests/expectations/both/body.compat.c b/tests/expectations/both/body.compat.c index bb15aabd..46b11c73 100644 --- a/tests/expectations/both/body.compat.c +++ b/tests/expectations/both/body.compat.c @@ -9,6 +9,12 @@ typedef enum MyCLikeEnum { Baz1, } MyCLikeEnum; +typedef enum MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +} MyCLikeEnum_Prepended; + typedef struct MyFancyStruct { int32_t i; #ifdef __cplusplus @@ -47,11 +53,56 @@ typedef union MyUnion { int32_t extra_member; // yolo } MyUnion; +typedef struct MyFancyStruct_Prepended { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +} MyFancyStruct_Prepended; + +typedef enum MyFancyEnum_Prepended_Tag { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +} MyFancyEnum_Prepended_Tag; + +typedef struct Bar_Prepended_Body { + int32_t _0; +} Bar_Prepended_Body; + +typedef struct Baz_Prepended_Body { + int32_t _0; +} Baz_Prepended_Body; + +typedef struct MyFancyEnum_Prepended { + #ifdef __cplusplus + inline void wohoo(); + #endif + MyFancyEnum_Prepended_Tag tag; + union { + Bar_Prepended_Body bar_prepended; + Baz_Prepended_Body baz_prepended; + }; +} MyFancyEnum_Prepended; + +typedef union MyUnion_Prepended { + int32_t extra_member; // yolo + float f; + uint32_t u; +} MyUnion_Prepended; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(MyFancyStruct s, MyFancyEnum e, MyCLikeEnum c, MyUnion u); +void root(MyFancyStruct s, + MyFancyEnum e, + MyCLikeEnum c, + MyUnion u, + MyFancyStruct_Prepended sp, + MyFancyEnum_Prepended ep, + MyCLikeEnum_Prepended cp, + MyUnion_Prepended up); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/tag/body.c b/tests/expectations/tag/body.c index 97bdcb70..fd3125e0 100644 --- a/tests/expectations/tag/body.c +++ b/tests/expectations/tag/body.c @@ -9,6 +9,12 @@ enum MyCLikeEnum { Baz1, }; +enum MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +}; + struct MyFancyStruct { int32_t i; #ifdef __cplusplus @@ -47,4 +53,49 @@ union MyUnion { int32_t extra_member; // yolo }; -void root(struct MyFancyStruct s, struct MyFancyEnum e, enum MyCLikeEnum c, union MyUnion u); +struct MyFancyStruct_Prepended { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +}; + +enum MyFancyEnum_Prepended_Tag { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +}; + +struct Bar_Prepended_Body { + int32_t _0; +}; + +struct Baz_Prepended_Body { + int32_t _0; +}; + +struct MyFancyEnum_Prepended { + #ifdef __cplusplus + inline void wohoo(); + #endif + enum MyFancyEnum_Prepended_Tag tag; + union { + struct Bar_Prepended_Body bar_prepended; + struct Baz_Prepended_Body baz_prepended; + }; +}; + +union MyUnion_Prepended { + int32_t extra_member; // yolo + float f; + uint32_t u; +}; + +void root(struct MyFancyStruct s, + struct MyFancyEnum e, + enum MyCLikeEnum c, + union MyUnion u, + struct MyFancyStruct_Prepended sp, + struct MyFancyEnum_Prepended ep, + enum MyCLikeEnum_Prepended cp, + union MyUnion_Prepended up); diff --git a/tests/expectations/tag/body.compat.c b/tests/expectations/tag/body.compat.c index 5d43001d..9b1e657c 100644 --- a/tests/expectations/tag/body.compat.c +++ b/tests/expectations/tag/body.compat.c @@ -9,6 +9,12 @@ enum MyCLikeEnum { Baz1, }; +enum MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +}; + struct MyFancyStruct { int32_t i; #ifdef __cplusplus @@ -47,11 +53,56 @@ union MyUnion { int32_t extra_member; // yolo }; +struct MyFancyStruct_Prepended { +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif + int32_t i; +}; + +enum MyFancyEnum_Prepended_Tag { + Foo_Prepended, + Bar_Prepended, + Baz_Prepended, +}; + +struct Bar_Prepended_Body { + int32_t _0; +}; + +struct Baz_Prepended_Body { + int32_t _0; +}; + +struct MyFancyEnum_Prepended { + #ifdef __cplusplus + inline void wohoo(); + #endif + enum MyFancyEnum_Prepended_Tag tag; + union { + struct Bar_Prepended_Body bar_prepended; + struct Baz_Prepended_Body baz_prepended; + }; +}; + +union MyUnion_Prepended { + int32_t extra_member; // yolo + float f; + uint32_t u; +}; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(struct MyFancyStruct s, struct MyFancyEnum e, enum MyCLikeEnum c, union MyUnion u); +void root(struct MyFancyStruct s, + struct MyFancyEnum e, + enum MyCLikeEnum c, + union MyUnion u, + struct MyFancyStruct_Prepended sp, + struct MyFancyEnum_Prepended ep, + enum MyCLikeEnum_Prepended cp, + union MyUnion_Prepended up); #ifdef __cplusplus } // extern "C" diff --git a/tests/rust/body.rs b/tests/rust/body.rs index 31dc0c24..fb275f9f 100644 --- a/tests/rust/body.rs +++ b/tests/rust/body.rs @@ -24,5 +24,32 @@ pub union MyUnion { pub u: u32, } + +#[repr(C)] +pub struct MyFancyStruct_Prepended { + i: i32, +} + +#[repr(C)] +pub enum MyFancyEnum_Prepended { + Foo_Prepended, + Bar_Prepended(i32), + Baz_Prepended(i32), +} + +#[repr(C)] +pub enum MyCLikeEnum_Prepended { + Foo1_Prepended, + Bar1_Prepended, + Baz1_Prepended, +} + +#[repr(C)] +pub union MyUnion_Prepended { + pub f: f32, + pub u: u32, +} + + #[no_mangle] -pub extern "C" fn root(s: MyFancyStruct, e: MyFancyEnum, c: MyCLikeEnum, u: MyUnion) {} +pub extern "C" fn root(s: MyFancyStruct, e: MyFancyEnum, c: MyCLikeEnum, u: MyUnion, sp: MyFancyStruct_Prepended, ep: MyFancyEnum_Prepended, cp: MyCLikeEnum_Prepended, up: MyUnion_Prepended) {} diff --git a/tests/rust/body.toml b/tests/rust/body.toml index 977f7f67..973a47fd 100644 --- a/tests/rust/body.toml +++ b/tests/rust/body.toml @@ -18,3 +18,25 @@ "MyUnion" = """ int32_t extra_member; // yolo """ + +[export.pre_body] +"MyFancyStruct_Prepended" = """ +#ifdef __cplusplus + inline void prepended_wohoo(); +#endif +""" + +"MyFancyEnum_Prepended" = """ + #ifdef __cplusplus + inline void wohoo(); + #endif +""" + +"MyCLikeEnum_Prepended" = """ + BogusVariantForSerializationForExample, +""" + +"MyUnion_Prepended" = """ + int32_t extra_member; // yolo +""" +