133d722a9Sopenharmony_ci{{#title rust::Box<T> — Rust ♡ C++}} 233d722a9Sopenharmony_ci# rust::Box\<T\> 333d722a9Sopenharmony_ci 433d722a9Sopenharmony_ci### Public API: 533d722a9Sopenharmony_ci 633d722a9Sopenharmony_ci```cpp,hidelines 733d722a9Sopenharmony_ci// rust/cxx.h 833d722a9Sopenharmony_ci# 933d722a9Sopenharmony_ci# #include <type_traits> 1033d722a9Sopenharmony_ci# 1133d722a9Sopenharmony_ci# namespace rust { 1233d722a9Sopenharmony_ci 1333d722a9Sopenharmony_citemplate <typename T> 1433d722a9Sopenharmony_ciclass Box final { 1533d722a9Sopenharmony_cipublic: 1633d722a9Sopenharmony_ci using element_type = T; 1733d722a9Sopenharmony_ci using const_pointer = 1833d722a9Sopenharmony_ci typename std::add_pointer<typename std::add_const<T>::type>::type; 1933d722a9Sopenharmony_ci using pointer = typename std::add_pointer<T>::type; 2033d722a9Sopenharmony_ci 2133d722a9Sopenharmony_ci Box(Box &&) noexcept; 2233d722a9Sopenharmony_ci ~Box() noexcept; 2333d722a9Sopenharmony_ci 2433d722a9Sopenharmony_ci explicit Box(const T &); 2533d722a9Sopenharmony_ci explicit Box(T &&); 2633d722a9Sopenharmony_ci 2733d722a9Sopenharmony_ci Box &operator=(Box &&) noexcept; 2833d722a9Sopenharmony_ci 2933d722a9Sopenharmony_ci const T *operator->() const noexcept; 3033d722a9Sopenharmony_ci const T &operator*() const noexcept; 3133d722a9Sopenharmony_ci T *operator->() noexcept; 3233d722a9Sopenharmony_ci T &operator*() noexcept; 3333d722a9Sopenharmony_ci 3433d722a9Sopenharmony_ci template <typename... Fields> 3533d722a9Sopenharmony_ci static Box in_place(Fields &&...); 3633d722a9Sopenharmony_ci 3733d722a9Sopenharmony_ci void swap(Box &) noexcept; 3833d722a9Sopenharmony_ci 3933d722a9Sopenharmony_ci // Important: requires that `raw` came from an into_raw call. Do not 4033d722a9Sopenharmony_ci // pass a pointer from `new` or any other source. 4133d722a9Sopenharmony_ci static Box from_raw(T *) noexcept; 4233d722a9Sopenharmony_ci 4333d722a9Sopenharmony_ci T *into_raw() noexcept; 4433d722a9Sopenharmony_ci}; 4533d722a9Sopenharmony_ci# 4633d722a9Sopenharmony_ci# } // namespace rust 4733d722a9Sopenharmony_ci``` 4833d722a9Sopenharmony_ci 4933d722a9Sopenharmony_ci### Restrictions: 5033d722a9Sopenharmony_ci 5133d722a9Sopenharmony_ciBox\<T\> does not support T being an opaque C++ type. You should use 5233d722a9Sopenharmony_ci[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for 5333d722a9Sopenharmony_citransferring ownership of opaque C++ types on the language boundary. 5433d722a9Sopenharmony_ci 5533d722a9Sopenharmony_ciIf T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size 5633d722a9Sopenharmony_ciknown at compile time. In the future we may introduce support for dynamically 5733d722a9Sopenharmony_cisized opaque Rust types. 5833d722a9Sopenharmony_ci 5933d722a9Sopenharmony_ci[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html 6033d722a9Sopenharmony_ci 6133d722a9Sopenharmony_ci## Example 6233d722a9Sopenharmony_ci 6333d722a9Sopenharmony_ciThis program uses a Box to pass ownership of some opaque piece of Rust state 6433d722a9Sopenharmony_ciover to C++ and then back to a Rust callback, which is a useful pattern for 6533d722a9Sopenharmony_ciimplementing [async functions over FFI](../async.md). 6633d722a9Sopenharmony_ci 6733d722a9Sopenharmony_ci```rust,noplayground 6833d722a9Sopenharmony_ci// src/main.rs 6933d722a9Sopenharmony_ci 7033d722a9Sopenharmony_ciuse std::io::Write; 7133d722a9Sopenharmony_ci 7233d722a9Sopenharmony_ci#[cxx::bridge] 7333d722a9Sopenharmony_cimod ffi { 7433d722a9Sopenharmony_ci extern "Rust" { 7533d722a9Sopenharmony_ci type File; 7633d722a9Sopenharmony_ci } 7733d722a9Sopenharmony_ci 7833d722a9Sopenharmony_ci unsafe extern "C++" { 7933d722a9Sopenharmony_ci include!("example/include/example.h"); 8033d722a9Sopenharmony_ci 8133d722a9Sopenharmony_ci fn f( 8233d722a9Sopenharmony_ci callback: fn(Box<File>, fst: &str, snd: &str), 8333d722a9Sopenharmony_ci out: Box<File>, 8433d722a9Sopenharmony_ci ); 8533d722a9Sopenharmony_ci } 8633d722a9Sopenharmony_ci} 8733d722a9Sopenharmony_ci 8833d722a9Sopenharmony_cipub struct File(std::fs::File); 8933d722a9Sopenharmony_ci 9033d722a9Sopenharmony_cifn main() { 9133d722a9Sopenharmony_ci let out = std::fs::File::create("example.log").unwrap(); 9233d722a9Sopenharmony_ci 9333d722a9Sopenharmony_ci ffi::f( 9433d722a9Sopenharmony_ci |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); }, 9533d722a9Sopenharmony_ci Box::new(File(out)), 9633d722a9Sopenharmony_ci ); 9733d722a9Sopenharmony_ci} 9833d722a9Sopenharmony_ci``` 9933d722a9Sopenharmony_ci 10033d722a9Sopenharmony_ci```cpp 10133d722a9Sopenharmony_ci// include/example.h 10233d722a9Sopenharmony_ci 10333d722a9Sopenharmony_ci#pragma once 10433d722a9Sopenharmony_ci#include "example/src/main.rs.h" 10533d722a9Sopenharmony_ci#include "rust/cxx.h" 10633d722a9Sopenharmony_ci 10733d722a9Sopenharmony_civoid f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, 10833d722a9Sopenharmony_ci rust::Box<File> out); 10933d722a9Sopenharmony_ci``` 11033d722a9Sopenharmony_ci 11133d722a9Sopenharmony_ci```cpp 11233d722a9Sopenharmony_ci// include/example.cc 11333d722a9Sopenharmony_ci 11433d722a9Sopenharmony_ci#include "example/include/example.h" 11533d722a9Sopenharmony_ci 11633d722a9Sopenharmony_civoid f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, 11733d722a9Sopenharmony_ci rust::Box<File> out) { 11833d722a9Sopenharmony_ci callback(std::move(out), "fearless", "concurrency"); 11933d722a9Sopenharmony_ci} 12033d722a9Sopenharmony_ci``` 121