Skip to content

Commit 7f0f60f

Browse files
authored
Merge pull request #437 from dtolnay/methods
Support methods/member functions on shared structs
2 parents 2e15992 + 464aeeb commit 7f0f60f

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

gen/src/write.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
6666
fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
6767
let mut methods_for_type = HashMap::new();
6868
for api in apis {
69-
if let Api::RustFunction(efn) = api {
69+
if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
7070
if let Some(receiver) = &efn.sig.receiver {
7171
methods_for_type
7272
.entry(&receiver.ty.rust)
@@ -84,7 +84,11 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
8484
for next in &mut toposorted_structs {
8585
if !out.types.cxx.contains(&strct.name.rust) {
8686
out.next_section();
87-
write_struct(out, next);
87+
let methods = methods_for_type
88+
.get(&strct.name.rust)
89+
.map(Vec::as_slice)
90+
.unwrap_or_default();
91+
write_struct(out, next, methods);
8892
}
8993
structs_written.insert(&next.name.rust);
9094
if next.name.rust == strct.name.rust {
@@ -173,7 +177,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
173177
}
174178
}
175179

176-
fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
180+
fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
177181
out.set_namespace(&strct.name.namespace);
178182
let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.to_symbol());
179183
writeln!(out, "#ifndef {}", guard);
@@ -187,6 +191,16 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
187191
write_type_space(out, &field.ty);
188192
writeln!(out, "{};", field.ident);
189193
}
194+
if !methods.is_empty() {
195+
writeln!(out);
196+
}
197+
for method in methods {
198+
write!(out, " ");
199+
let sig = &method.sig;
200+
let local_name = method.name.cxx.to_string();
201+
write_rust_function_shim_decl(out, &local_name, sig, false);
202+
writeln!(out, ";");
203+
}
190204
writeln!(out, "}};");
191205
writeln!(out, "#endif // {}", guard);
192206
}

tests/ffi/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ pub mod ffi {
202202
fn set2(&mut self, n: usize) -> usize;
203203
fn set_succeed(&mut self, n: usize) -> Result<usize>;
204204
fn get_fail(&mut self) -> Result<usize>;
205+
fn c_method_on_shared(self: &Shared) -> usize;
205206

206207
#[rust_name = "i32_overloaded_method"]
207208
fn cOverloadedMethod(&self, x: i32) -> String;
@@ -273,6 +274,7 @@ pub mod ffi {
273274
fn r_return_r2(n: usize) -> Box<R2>;
274275
fn get(self: &R2) -> usize;
275276
fn set(self: &mut R2, n: usize) -> usize;
277+
fn r_method_on_shared(self: &Shared) -> usize;
276278

277279
#[cxx_name = "rAliasedFunction"]
278280
fn r_aliased_function(x: i32) -> String;
@@ -315,6 +317,12 @@ impl R2 {
315317
}
316318
}
317319

320+
impl ffi::Shared {
321+
fn r_method_on_shared(&self) -> usize {
322+
2020
323+
}
324+
}
325+
318326
#[derive(Debug)]
319327
struct Error;
320328

tests/ffi/tests.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ size_t C::set_succeed(size_t n) { return this->set2(n); }
3535

3636
size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
3737

38+
size_t Shared::c_method_on_shared() const noexcept { return 2021; }
39+
3840
const std::vector<uint8_t> &C::get_v() const { return this->v; }
3941

4042
std::vector<uint8_t> &C::get_v() { return this->v; }
@@ -624,6 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
624626
ASSERT(r2->get() == 2021);
625627
ASSERT(r2->set(2020) == 2020);
626628
ASSERT(r2->get() == 2020);
629+
ASSERT(Shared{0}.r_method_on_shared() == 2020);
627630

628631
ASSERT(std::string(rAliasedFunction(2020)) == "2020");
629632

tests/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ fn test_c_method_calls() {
193193
assert_eq!(old_value, unique_ptr.get2());
194194
assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
195195
assert!(unique_ptr.get_fail().is_err());
196+
assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
196197
}
197198

198199
#[test]

0 commit comments

Comments
 (0)