summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris-Chengbiao Zhou <bobo1239@web.de>2021-04-30 02:16:49 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2021-04-30 10:57:18 +0200
commit49430588d720dbb99f6694f7742c1462d36ca01a (patch)
treebf22fc512b75434ac2f5a8bdb04bcf5bd220bf8a
parent425a14617a9b807e51f37610385a24a0485d89fc (diff)
Add a C naming option (#2045)
Closes #2045. Fixes #1252.
-rw-r--r--src/ir/item.rs24
-rw-r--r--src/lib.rs17
-rw-r--r--src/options.rs7
-rw-r--r--tests/expectations/tests/c_naming.rs92
-rw-r--r--tests/headers/c_naming.h19
5 files changed, 158 insertions, 1 deletions
diff --git a/src/ir/item.rs b/src/ir/item.rs
index ffb52664..9375c798 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -4,7 +4,7 @@ use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
use super::annotations::Annotations;
use super::comment;
-use super::comp::MethodKind;
+use super::comp::{CompKind, MethodKind};
use super::context::{BindgenContext, ItemId, PartialType, TypeId};
use super::derive::{
CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
@@ -904,6 +904,12 @@ impl Item {
names.push(base_name);
}
+ if ctx.options().c_naming {
+ if let Some(prefix) = self.c_naming_prefix() {
+ names.insert(0, prefix.to_string());
+ }
+ }
+
let name = names.join("_");
let name = if opt.user_mangled == UserMangled::Yes {
@@ -1054,6 +1060,22 @@ impl Item {
path.reverse();
path
}
+
+ /// Returns a prefix for the canonical name when C naming is enabled.
+ fn c_naming_prefix(&self) -> Option<&str> {
+ if let ItemKind::Type(typ) = &self.kind {
+ match typ.kind() {
+ TypeKind::Comp(comp_info) => match comp_info.kind() {
+ CompKind::Struct => Some("struct"),
+ CompKind::Union => Some("union"),
+ },
+ TypeKind::Enum(_) => Some("enum"),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
}
impl<T> IsOpaque for T
diff --git a/src/lib.rs b/src/lib.rs
index 58c99c8d..1ac053b7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -558,6 +558,10 @@ impl Builder {
output_vector.push("--translate-enum-integer-types".into());
}
+ if self.options.c_naming {
+ output_vector.push("--c-naming".into());
+ }
+
// Add clang arguments
output_vector.push("--".into());
@@ -1616,6 +1620,15 @@ impl Builder {
self.options.translate_enum_integer_types = doit;
self
}
+
+ /// Generate types with C style naming.
+ ///
+ /// This will add prefixes to the generated type names. For example instead of a struct `A` we
+ /// will generate struct `struct_A`. Currently applies to structs, unions, and enums.
+ pub fn c_naming(mut self, doit: bool) -> Self {
+ self.options.c_naming = doit;
+ self
+ }
}
/// Configuration options for generated bindings.
@@ -1921,6 +1934,9 @@ struct BindgenOptions {
/// Always translate enum integer types to native Rust integer types.
translate_enum_integer_types: bool,
+
+ /// Generate types with C style naming.
+ c_naming: bool,
}
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2062,6 +2078,7 @@ impl Default for BindgenOptions {
dynamic_link_require_all: false,
respect_cxx_access_specs: false,
translate_enum_integer_types: false,
+ c_naming: false,
}
}
}
diff --git a/src/options.rs b/src/options.rs
index ff2d4282..cbdc945e 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -513,6 +513,9 @@ where
Arg::with_name("translate-enum-integer-types")
.long("translate-enum-integer-types")
.help("Always translate enum integer types to native Rust integer types."),
+ Arg::with_name("c-naming")
+ .long("c-naming")
+ .help("Generate types with C style naming."),
]) // .args()
.get_matches_from(args);
@@ -953,6 +956,10 @@ where
builder = builder.translate_enum_integer_types(true);
}
+ if matches.is_present("c-naming") {
+ builder = builder.c_naming(true);
+ }
+
let verbose = matches.is_present("verbose");
Ok((builder, output, verbose))
diff --git a/tests/expectations/tests/c_naming.rs b/tests/expectations/tests/c_naming.rs
new file mode 100644
index 00000000..041e75ea
--- /dev/null
+++ b/tests/expectations/tests/c_naming.rs
@@ -0,0 +1,92 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct struct_a {
+ pub a: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_struct_a() {
+ assert_eq!(
+ ::std::mem::size_of::<struct_a>(),
+ 4usize,
+ concat!("Size of: ", stringify!(struct_a))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<struct_a>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(struct_a))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<struct_a>())).a as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(struct_a),
+ "::",
+ stringify!(a)
+ )
+ );
+}
+pub type a = *const struct_a;
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union union_b {
+ pub a: ::std::os::raw::c_int,
+ pub b: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_union_b() {
+ assert_eq!(
+ ::std::mem::size_of::<union_b>(),
+ 4usize,
+ concat!("Size of: ", stringify!(union_b))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<union_b>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(union_b))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<union_b>())).a as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(union_b),
+ "::",
+ stringify!(a)
+ )
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<union_b>())).b as *const _ as usize },
+ 0usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(union_b),
+ "::",
+ stringify!(b)
+ )
+ );
+}
+impl Default for union_b {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
+pub type b = union_b;
+pub const enum_c_A: enum_c = 0;
+pub type enum_c = ::std::os::raw::c_uint;
+extern "C" {
+ pub fn takes_a(arg: a);
+}
+extern "C" {
+ pub fn takes_b(arg: b);
+}
+extern "C" {
+ pub fn takes_c(arg: enum_c);
+}
diff --git a/tests/headers/c_naming.h b/tests/headers/c_naming.h
new file mode 100644
index 00000000..fd84c271
--- /dev/null
+++ b/tests/headers/c_naming.h
@@ -0,0 +1,19 @@
+// bindgen-flags: --c-naming
+
+typedef const struct a {
+ int a;
+} *a;
+
+union b {
+ int a;
+ int b;
+};
+typedef union b b;
+
+enum c {
+ A,
+};
+
+void takes_a(a arg) {}
+void takes_b(b arg) {}
+void takes_c(enum c arg) {}