Merge pull request #437 from dtolnay/methods
Support methods/member functions on shared structs
diff --git a/gen/src/write.rs b/gen/src/write.rs
index b8d1dd4..39053a1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -66,7 +66,7 @@
fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
let mut methods_for_type = HashMap::new();
for api in apis {
- if let Api::RustFunction(efn) = api {
+ if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
if let Some(receiver) = &efn.sig.receiver {
methods_for_type
.entry(&receiver.ty.rust)
@@ -84,7 +84,11 @@
for next in &mut toposorted_structs {
if !out.types.cxx.contains(&strct.name.rust) {
out.next_section();
- write_struct(out, next);
+ let methods = methods_for_type
+ .get(&strct.name.rust)
+ .map(Vec::as_slice)
+ .unwrap_or_default();
+ write_struct(out, next, methods);
}
structs_written.insert(&next.name.rust);
if next.name.rust == strct.name.rust {
@@ -173,7 +177,7 @@
}
}
-fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
out.set_namespace(&strct.name.namespace);
let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.to_symbol());
writeln!(out, "#ifndef {}", guard);
@@ -187,6 +191,16 @@
write_type_space(out, &field.ty);
writeln!(out, "{};", field.ident);
}
+ if !methods.is_empty() {
+ writeln!(out);
+ }
+ for method in methods {
+ write!(out, " ");
+ let sig = &method.sig;
+ let local_name = method.name.cxx.to_string();
+ write_rust_function_shim_decl(out, &local_name, sig, false);
+ writeln!(out, ";");
+ }
writeln!(out, "}};");
writeln!(out, "#endif // {}", guard);
}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9ea3450..96f9b07 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -202,6 +202,7 @@
fn set2(&mut self, n: usize) -> usize;
fn set_succeed(&mut self, n: usize) -> Result<usize>;
fn get_fail(&mut self) -> Result<usize>;
+ fn c_method_on_shared(self: &Shared) -> usize;
#[rust_name = "i32_overloaded_method"]
fn cOverloadedMethod(&self, x: i32) -> String;
@@ -273,6 +274,7 @@
fn r_return_r2(n: usize) -> Box<R2>;
fn get(self: &R2) -> usize;
fn set(self: &mut R2, n: usize) -> usize;
+ fn r_method_on_shared(self: &Shared) -> usize;
#[cxx_name = "rAliasedFunction"]
fn r_aliased_function(x: i32) -> String;
@@ -315,6 +317,12 @@
}
}
+impl ffi::Shared {
+ fn r_method_on_shared(&self) -> usize {
+ 2020
+ }
+}
+
#[derive(Debug)]
struct Error;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 747788f..fd4751e 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,6 +35,8 @@
size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
+size_t Shared::c_method_on_shared() const noexcept { return 2021; }
+
const std::vector<uint8_t> &C::get_v() const { return this->v; }
std::vector<uint8_t> &C::get_v() { return this->v; }
@@ -624,6 +626,7 @@
ASSERT(r2->get() == 2021);
ASSERT(r2->set(2020) == 2020);
ASSERT(r2->get() == 2020);
+ ASSERT(Shared{0}.r_method_on_shared() == 2020);
ASSERT(std::string(rAliasedFunction(2020)) == "2020");
diff --git a/tests/test.rs b/tests/test.rs
index e3f9fce..a2c64c3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -193,6 +193,7 @@
assert_eq!(old_value, unique_ptr.get2());
assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
assert!(unique_ptr.get_fail().is_err());
+ assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
}
#[test]