1{{#title rust::Box<T> — Rust ♡ C++}} 2# rust::Box\<T\> 3 4### Public API: 5 6```cpp,hidelines 7// rust/cxx.h 8# 9# #include <type_traits> 10# 11# namespace rust { 12 13template <typename T> 14class Box final { 15public: 16 using element_type = T; 17 using const_pointer = 18 typename std::add_pointer<typename std::add_const<T>::type>::type; 19 using pointer = typename std::add_pointer<T>::type; 20 21 Box(Box &&) noexcept; 22 ~Box() noexcept; 23 24 explicit Box(const T &); 25 explicit Box(T &&); 26 27 Box &operator=(Box &&) noexcept; 28 29 const T *operator->() const noexcept; 30 const T &operator*() const noexcept; 31 T *operator->() noexcept; 32 T &operator*() noexcept; 33 34 template <typename... Fields> 35 static Box in_place(Fields &&...); 36 37 void swap(Box &) noexcept; 38 39 // Important: requires that `raw` came from an into_raw call. Do not 40 // pass a pointer from `new` or any other source. 41 static Box from_raw(T *) noexcept; 42 43 T *into_raw() noexcept; 44}; 45# 46# } // namespace rust 47``` 48 49### Restrictions: 50 51Box\<T\> does not support T being an opaque C++ type. You should use 52[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for 53transferring ownership of opaque C++ types on the language boundary. 54 55If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size 56known at compile time. In the future we may introduce support for dynamically 57sized opaque Rust types. 58 59[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html 60 61## Example 62 63This program uses a Box to pass ownership of some opaque piece of Rust state 64over to C++ and then back to a Rust callback, which is a useful pattern for 65implementing [async functions over FFI](../async.md). 66 67```rust,noplayground 68// src/main.rs 69 70use std::io::Write; 71 72#[cxx::bridge] 73mod ffi { 74 extern "Rust" { 75 type File; 76 } 77 78 unsafe extern "C++" { 79 include!("example/include/example.h"); 80 81 fn f( 82 callback: fn(Box<File>, fst: &str, snd: &str), 83 out: Box<File>, 84 ); 85 } 86} 87 88pub struct File(std::fs::File); 89 90fn main() { 91 let out = std::fs::File::create("example.log").unwrap(); 92 93 ffi::f( 94 |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); }, 95 Box::new(File(out)), 96 ); 97} 98``` 99 100```cpp 101// include/example.h 102 103#pragma once 104#include "example/src/main.rs.h" 105#include "rust/cxx.h" 106 107void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, 108 rust::Box<File> out); 109``` 110 111```cpp 112// include/example.cc 113 114#include "example/include/example.h" 115 116void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, 117 rust::Box<File> out) { 118 callback(std::move(out), "fearless", "concurrency"); 119} 120``` 121