Support calling C++ methods from Rust
These methods can be declared in the bridge by naming the first
argument self and making it a reference to the containing class, e.g.,
fn get(self: &C) -> usize;
fn set(self: &mut C, n: usize);
This syntax requires Rust 1.43.
Note that the implementation also changes the internal naming of shim
functions so that they also contain the name of the owning class, if
any. This allows defining multiple methods with the same name on
different objects.
diff --git a/gen/write.rs b/gen/write.rs
index 322ca08..41b5b37 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@
use crate::gen::out::OutFile;
use crate::gen::{include, Opt};
use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Signature, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, Receiver, Signature, Struct, Type, Types, Var};
use proc_macro2::Ident;
pub(super) fn gen(
@@ -327,8 +327,11 @@
write_extern_return_type_space(out, &efn.ret, types);
}
write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
+ if let Some(base) = &efn.receiver {
+ write!(out, "{} *__receiver$", base.ident);
+ }
for (i, arg) in efn.args.iter().enumerate() {
- if i > 0 {
+ if i > 0 || efn.receiver.is_some() {
write!(out, ", ");
}
if arg.ty == RustString {
@@ -347,14 +350,27 @@
writeln!(out, ") noexcept {{");
write!(out, " ");
write_return_type(out, &efn.ret);
- write!(out, "(*{}$)(", efn.ident);
+ match &efn.receiver {
+ None => write!(out, "(*{}$)(", efn.ident),
+ Some(base) => write!(out, "({}::*{}$)(", base.ident, efn.ident),
+ }
for (i, arg) in efn.args.iter().enumerate() {
if i > 0 {
write!(out, ", ");
}
write_type(out, &arg.ty);
}
- writeln!(out, ") = {};", efn.ident);
+ write!(out, ")");
+ match &efn.receiver {
+ Some(Receiver { mutability: None, ident: _ }) => write!(out, " const"),
+ _ => {},
+ }
+ write!(out, " = ");
+ match &efn.receiver {
+ None => write!(out, "{}", efn.ident),
+ Some(base) => write!(out, "&{}::{}", base.ident, efn.ident),
+ }
+ writeln!(out, ";");
write!(out, " ");
if efn.throws {
writeln!(out, "::rust::Str::Repr throw$;");
@@ -377,7 +393,10 @@
}
_ => {}
}
- write!(out, "{}$(", efn.ident);
+ match &efn.receiver {
+ None => write!(out, "{}$(", efn.ident),
+ Some(_) => write!(out, "(__receiver$->*{}$)(", efn.ident),
+ }
for (i, arg) in efn.args.iter().enumerate() {
if i > 0 {
write!(out, ", ");