-
Notifications
You must be signed in to change notification settings - Fork 337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support calling C++ and Rust methods #121
Conversation
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.
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: &R) -> usize; fn set(self: &mut R, n: usize); This syntax requires Rust 1.43.
Thanks, this is great! I'll get a chance to review the implementation tomorrow. If someone needs method support on 1.42 and isn't satisfied waiting for the 1.43 release, it would be possible for us to accept |
This is great, I can really use this. |
gen/write.rs
Outdated
writeln!(out, "struct {} final {{", ety.ident); | ||
for method in methods { | ||
write!(out, " "); | ||
let sig = &method.sig; | ||
let local_name = method.ident.to_string(); | ||
write_rust_function_shim_decl(out, &local_name, sig, None, false); | ||
writeln!(out, ";"); | ||
} | ||
writeln!(out, "}};"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a private or deleted default constructor and copy constructor in here. Otherwise this allows C++ to obtain an opaque Rust type by value and call methods on it, which is unsound.
Specifically the R2 struct from tests/ffi/lib.rs currently turns into:
struct R2 final {
size_t get() noexcept;
size_t set(size_t n) noexcept;
};
and this allows C++ to write R2{}.get()
which becomes UB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks good to me. I'm not sure if it's marked Draft because you are still working on it but feel free to send follow-up PRs as needed.
One note: I am going to remove the changes from demo-rs and the readme, since I'd like to keep that first intro code snippet as focused as possible on the most important concepts. We'll need to figure out somewhere else to put exhaustive documentation of the full feature set (namespace
is another; #86) rather than frontloading everything in that first snippet.
I marked it as a draft because I thought we wanted to wait until Rust 1.43 was released, but it looks like you dealt with that as a follow-up. Thanks! |
This adds support for calling C++ and Rust methods with the syntax suggested in #51:
fn get_name(self: &ThingC) -> &CxxString;
fn print(self: &ThingR);
It requires Rust 1.43 to use this syntax.