Add option to generate C headers with C++ compatibility
By default C++ compatibility is disabled.
This commit is contained in:
parent
767fce25d1
commit
bbeff3e3aa
@ -208,12 +208,24 @@ impl Bindings {
|
||||
}
|
||||
|
||||
if !self.functions.is_empty() || !self.globals.is_empty() {
|
||||
if self.config.language == Language::Cxx {
|
||||
if self.config.language == Language::C && self.config.cpp_compat {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#ifdef __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx || self.config.cpp_compat {
|
||||
out.new_line_if_not_start();
|
||||
out.write("extern \"C\" {");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::C && self.config.cpp_compat {
|
||||
out.new_line();
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
for global in &self.globals {
|
||||
out.new_line_if_not_start();
|
||||
global.write(&self.config, &mut out);
|
||||
@ -226,11 +238,23 @@ impl Bindings {
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx {
|
||||
out.new_line_if_not_start();
|
||||
if self.config.language == Language::C && self.config.cpp_compat {
|
||||
out.new_line();
|
||||
out.write("#ifdef __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx || self.config.cpp_compat {
|
||||
out.new_line();
|
||||
out.write("} // extern \"C\"");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if self.config.language == Language::C && self.config.cpp_compat {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
|
||||
if self.config.language == Language::Cxx {
|
||||
|
@ -613,6 +613,8 @@ pub struct Config {
|
||||
pub tab_width: usize,
|
||||
/// The language to output bindings for
|
||||
pub language: Language,
|
||||
/// Include preprocessor defines in C bindings to ensure C++ compatibility
|
||||
pub cpp_compat: bool,
|
||||
/// The style to declare structs, enums and unions in for C
|
||||
pub style: Style,
|
||||
/// The configuration options for parsing
|
||||
@ -658,6 +660,7 @@ impl Default for Config {
|
||||
line_length: 100,
|
||||
tab_width: 2,
|
||||
language: Language::Cxx,
|
||||
cpp_compat: false,
|
||||
style: Style::Type,
|
||||
macro_expansion: Default::default(),
|
||||
parse: ParseConfig::default(),
|
||||
|
@ -540,6 +540,18 @@ impl Source for Enum {
|
||||
if !size.is_none() || config.style.generate_tag() {
|
||||
write!(out, " {}", enum_name);
|
||||
}
|
||||
|
||||
if config.cpp_compat {
|
||||
if let Some(prim) = size {
|
||||
out.new_line();
|
||||
out.write("#ifdef __cplusplus");
|
||||
out.new_line();
|
||||
write!(out, " : {}", prim);
|
||||
out.new_line();
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.write("enum class");
|
||||
|
||||
@ -575,10 +587,22 @@ impl Source for Enum {
|
||||
}
|
||||
|
||||
if config.language == Language::C {
|
||||
if config.cpp_compat {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#ifndef __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
|
||||
if let Some(prim) = size {
|
||||
out.new_line();
|
||||
write!(out, "typedef {} {};", prim, enum_name);
|
||||
}
|
||||
|
||||
if config.cpp_compat {
|
||||
out.new_line_if_not_start();
|
||||
out.write("#endif // __cplusplus");
|
||||
out.new_line();
|
||||
}
|
||||
}
|
||||
// Done emitting the enum
|
||||
|
||||
|
@ -42,6 +42,10 @@ fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
|
||||
};
|
||||
}
|
||||
|
||||
if matches.is_present("cpp-compat") {
|
||||
config.cpp_compat = true;
|
||||
}
|
||||
|
||||
if let Some(style) = matches.value_of("style") {
|
||||
config.style = match style {
|
||||
"Both" => Style::Both,
|
||||
@ -141,6 +145,11 @@ fn main() {
|
||||
.help("Specify the language to output bindings in")
|
||||
.possible_values(&["c++", "C++", "c", "C"]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("cpp-compat")
|
||||
.long("cpp-compat")
|
||||
.help("Whether to add C++ compatibility to generated C bindings")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("style")
|
||||
.short("s")
|
||||
|
@ -10,6 +10,7 @@ fn run_cbindgen(
|
||||
path: &Path,
|
||||
output: &Path,
|
||||
language: Language,
|
||||
cpp_compat: bool,
|
||||
style: Option<Style>,
|
||||
) {
|
||||
let program = Path::new(cbindgen_path);
|
||||
@ -18,6 +19,10 @@ fn run_cbindgen(
|
||||
Language::Cxx => {}
|
||||
Language::C => {
|
||||
command.arg("--lang").arg("c");
|
||||
|
||||
if cpp_compat {
|
||||
command.arg("--cpp-compat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,6 +91,7 @@ fn run_compile_test(
|
||||
name: &'static str,
|
||||
path: &Path,
|
||||
language: Language,
|
||||
cpp_compat: bool,
|
||||
style: Option<Style>,
|
||||
) {
|
||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
@ -101,25 +107,35 @@ fn run_compile_test(
|
||||
Style::Type => {}
|
||||
}
|
||||
}
|
||||
match language {
|
||||
Language::Cxx => {
|
||||
output.push(format!("{}.cpp", name));
|
||||
}
|
||||
Language::C => {
|
||||
output.push(format!("{}.c", name));
|
||||
}
|
||||
}
|
||||
|
||||
run_cbindgen(cbindgen_path, path, &output, language, style);
|
||||
let ext = match language {
|
||||
Language::Cxx => "cpp",
|
||||
Language::C => {
|
||||
if cpp_compat {
|
||||
"compat.c"
|
||||
} else {
|
||||
"c"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
output.push(format!("{}.{}", name, ext));
|
||||
|
||||
run_cbindgen(cbindgen_path, path, &output, language, cpp_compat, style);
|
||||
compile(&output, language);
|
||||
|
||||
if language == Language::C && cpp_compat {
|
||||
compile(&output, Language::Cxx)
|
||||
}
|
||||
}
|
||||
|
||||
fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
|
||||
let test = Path::new(filename);
|
||||
for style in &[Style::Type, Style::Tag, Style::Both] {
|
||||
run_compile_test(cbindgen_path, name, &test, Language::C, Some(*style));
|
||||
run_compile_test(cbindgen_path, name, &test, Language::C, true, Some(*style));
|
||||
run_compile_test(cbindgen_path, name, &test, Language::C, false, Some(*style));
|
||||
}
|
||||
run_compile_test(cbindgen_path, name, &test, Language::Cxx, None);
|
||||
run_compile_test(cbindgen_path, name, &test, Language::Cxx, false, None);
|
||||
}
|
||||
|
||||
macro_rules! test_file {
|
||||
|
Loading…
x
Reference in New Issue
Block a user