From b7a7cb6785b63188c411a74db3f1eb05dce240b9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 17 Mar 2020 21:18:40 -0700 Subject: [PATCH] Provide more struct definitions where needed --- gen/include.rs | 8 +++++ gen/write.rs | 88 ++++++++++++++++++++++++++++++++++++++------------ include/cxx.h | 13 ++++++++ 3 files changed, 89 insertions(+), 20 deletions(-) diff --git a/gen/include.rs b/gen/include.rs index 68cb00d4..a7657e4a 100644 --- a/gen/include.rs +++ b/gen/include.rs @@ -29,8 +29,10 @@ fn find_line(line: &str) -> Option { #[derive(Default)] pub struct Includes { custom: Vec, + pub array: bool, pub cstdint: bool, pub cstring: bool, + pub exception: bool, pub memory: bool, pub string: bool, pub type_traits: bool, @@ -51,12 +53,18 @@ impl Display for Includes { for include in &self.custom { writeln!(f, "#include \"{}\"", include.escape_default())?; } + if self.array { + writeln!(f, "#include ")?; + } if self.cstdint { writeln!(f, "#include ")?; } if self.cstring { writeln!(f, "#include ")?; } + if self.exception { + writeln!(f, "#include ")?; + } if self.memory { writeln!(f, "#include ")?; } diff --git a/gen/write.rs b/gen/write.rs index 3398f9a8..a75d4c0e 100644 --- a/gen/write.rs +++ b/gen/write.rs @@ -97,47 +97,84 @@ fn write_includes(out: &mut OutFile, types: &Types) { } fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) { + let mut needs_rust_string = false; + let mut needs_rust_str = false; let mut needs_rust_box = false; for ty in types { - if let Type::RustBox(_) = ty { - needs_rust_box = true; - break; + match ty { + Type::RustBox(_) => { + out.include.type_traits = true; + needs_rust_box = true; + } + Type::Str(_) => { + out.include.cstdint = true; + out.include.string = true; + needs_rust_str = true; + } + ty if ty == RustString => { + out.include.array = true; + out.include.cstdint = true; + out.include.string = true; + needs_rust_string = true; + } + _ => {} } } + let mut needs_rust_error = false; + let mut needs_unsafe_bitcopy = false; let mut needs_manually_drop = false; let mut needs_maybe_uninit = false; for api in apis { - if let Api::RustFunction(efn) = api { - for arg in &efn.args { - if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) { - needs_manually_drop = true; - break; + match api { + Api::CxxFunction(efn) if !out.header => { + for arg in &efn.args { + if arg.ty == RustString { + needs_unsafe_bitcopy = true; + break; + } } } - if let Some(ret) = &efn.ret { - if types.needs_indirect_abi(ret) { - needs_maybe_uninit = true; + Api::RustFunction(efn) if !out.header => { + if efn.throws { + out.include.exception = true; + needs_rust_error = true; + } + for arg in &efn.args { + if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) { + needs_manually_drop = true; + break; + } + } + if let Some(ret) = &efn.ret { + if types.needs_indirect_abi(ret) { + needs_maybe_uninit = true; + } } } + _ => {} } } out.begin_block("namespace rust"); out.begin_block("inline namespace cxxbridge02"); - if needs_rust_box || needs_manually_drop || needs_maybe_uninit { + if needs_rust_string + || needs_rust_str + || needs_rust_box + || needs_rust_error + || needs_unsafe_bitcopy + || needs_manually_drop + || needs_maybe_uninit + { writeln!(out, "// #include \"rust/cxx.h\""); } - if needs_rust_box { - out.next_section(); - for line in include::get("CXXBRIDGE02_RUST_BOX").lines() { - if !line.trim_start().starts_with("//") { - writeln!(out, "{}", line); - } - } - } + write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING"); + write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR"); + write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX"); + write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR"); + write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY"); if needs_manually_drop { out.next_section(); @@ -166,6 +203,17 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) { out.end_block("namespace rust"); } +fn write_header_section(out: &mut OutFile, needed: bool, section: &str) { + if needed { + out.next_section(); + for line in include::get(section).lines() { + if !line.trim_start().starts_with("//") { + writeln!(out, "{}", line); + } + } + } +} + fn write_struct(out: &mut OutFile, strct: &Struct) { for line in strct.doc.to_string().lines() { writeln!(out, "//{}", line); diff --git a/include/cxx.h b/include/cxx.h index b48abb5b..a021ca74 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -10,6 +11,8 @@ inline namespace cxxbridge02 { struct unsafe_bitcopy_t; +#ifndef CXXBRIDGE02_RUST_STRING +#define CXXBRIDGE02_RUST_STRING class String final { public: String() noexcept; @@ -37,7 +40,10 @@ private: // Size and alignment statically verified by rust_string.rs. std::array repr; }; +#endif // CXXBRIDGE02_RUST_STRING +#ifndef CXXBRIDGE02_RUST_STR +#define CXXBRIDGE02_RUST_STR class Str final { public: Str() noexcept; @@ -70,6 +76,7 @@ public: private: Repr repr; }; +#endif // CXXBRIDGE02_RUST_STR #ifndef CXXBRIDGE02_RUST_BOX #define CXXBRIDGE02_RUST_BOX @@ -138,6 +145,8 @@ private: }; #endif // CXXBRIDGE02_RUST_BOX +#ifndef CXXBRIDGE02_RUST_ERROR +#define CXXBRIDGE02_RUST_ERROR class Error final : std::exception { public: Error(const Error &); @@ -149,6 +158,7 @@ public: private: Str::Repr msg; }; +#endif // CXXBRIDGE02_RUST_ERROR std::ostream &operator<<(std::ostream &, const String &); std::ostream &operator<<(std::ostream &, const Str &); @@ -159,10 +169,13 @@ using str = Str; template using box = Box; using error = Error; +#ifndef CXXBRIDGE02_RUST_BITCOPY +#define CXXBRIDGE02_RUST_BITCOPY struct unsafe_bitcopy_t { explicit unsafe_bitcopy_t() = default; }; constexpr unsafe_bitcopy_t unsafe_bitcopy{}; +#endif // CXXBRIDGE02_RUST_BITCOPY } // namespace cxxbridge02 } // namespace rust