Soundness fix: don't allow forgetting C++ values with lifetimes. Consider an RAII join handle for a thread: it _must_ be dropped before the end of the scope, or else the thread will keep running with invalid borrowed data. `SafeLeak` encapsulates all types which do not place requirements on destruction timing. It excludes types that require e.g. dropping at the end of their lifetime, such as a thread join handle. To do this, it forbids using the value anywhere but on the stack. This seems iffy wrt coroutines, but `impl Future` itself will require being allocated on the stack, and so on, recursively, tying it to a specific scope. This CL includes an `unsafe` escape hatch if a type is incorrectly annotated, or you promise to destroy it at the right time. PiperOrigin-RevId: 954451514
Crubit is a bidirectional bindings generator for C++ and Rust, with the goal of integrating the C++ and Rust ecosystems.
See the status page for an overview of the current supported features.
{{#tab name=“Calling Rust from C++”}}
Consider the following Rust library:
pub struct Account { pub id: u64, pub balance: f64, } impl std::fmt::Display for Account { ... } // Takes shared references, mapped to const references in C++. pub fn calculate_interest(account: &Account, rate: f64) -> f64 { ... } // Takes a string slice, mapped to rs_std::StrRef in C++. pub fn is_valid_username(username: &str) -> bool { ... }
You can call these Rust functions from C++:
#include "path/to/account.h" #include <iostream> void demo() { account::Account my_account{.id = 123, .balance = 1000.0}; double interest = account::calculate_interest(my_account, 0.05); // my_account is printable because Account implements Display in Rust! std::cout << my_account << std::endl; if (account::is_valid_username("bob")) { std::cout << "Valid user" << std::endl; } }
{{#tab name=“Calling C++ from Rust”}}
Consider the following C++ header:
#include <string_view> #include <optional> #include <memory> struct User { int id; double balance; }; std::optional<User> FindUser(int id); std::unique_ptr<User> CreateUser(std::string_view name, int id);
You can call these C++ functions from Rust:
use cc_std::std::unique_ptr; use ffi_11::{c_double, c_int}; use user_api::{CreateUser, FindUser, User}; let id: c_int = 123; let user: Option<User> = FindUser(id); if let Some(u) = user { let balance: c_double = u.balance; println!("User {} has balance {}", u.id, balance); } let new_user: unique_ptr<User> = CreateUser("Alice".into(), 456);
We have detailed walkthroughs on how to use C++ from Rust, or Rust from C++, using Crubit, as well as copy-pastable example code. The example code also includes spanshots of what the generated bindings look like.
examples/rust/examples/cpp/| Nightly | Stable |
|---|---|