Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a C naming option #2045

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/ir/item.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -1054,6 +1060,24 @@ 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
Expand Down
17 changes: 17 additions & 0 deletions src/lib.rs
Expand Up @@ -557,6 +557,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());
Expand Down Expand Up @@ -1600,6 +1604,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.
Expand Down Expand Up @@ -1899,6 +1912,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
Expand Down Expand Up @@ -2038,6 +2054,7 @@ impl Default for BindgenOptions {
dynamic_link_require_all: false,
respect_cxx_access_specs: false,
translate_enum_integer_types: false,
c_naming: false,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/options.rs
Expand Up @@ -509,6 +509,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);

Expand Down Expand Up @@ -943,6 +946,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))
Expand Down
92 changes: 92 additions & 0 deletions 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);
}
19 changes: 19 additions & 0 deletions 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) {}