| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 1 | CXX — safe FFI between Rust and C++ | 
 | 2 | ========================================= | 
 | 3 |  | 
| David Tolnay | dd3af09 | 2020-05-12 21:47:06 -0700 | [diff] [blame] | 4 | [<img alt="github" src="https://img.shields.io/badge/github-dtolnay/cxx-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/cxx) | 
 | 5 | [<img alt="crates.io" src="https://img.shields.io/crates/v/cxx.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/cxx) | 
 | 6 | [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/cxx) | 
 | 7 | [<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/cxx/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster) | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 8 |  | 
 | 9 | This library provides a **safe** mechanism for calling C++ code from Rust and | 
 | 10 | Rust code from C++, not subject to the many ways that things can go wrong when | 
 | 11 | using bindgen or cbindgen to generate unsafe C-style bindings. | 
 | 12 |  | 
| David Tolnay | ccd3975 | 2020-01-08 09:33:51 -0800 | [diff] [blame] | 13 | This doesn't change the fact that 100% of C++ code is unsafe. When auditing a | 
 | 14 | project, you would be on the hook for auditing all the unsafe Rust code and | 
 | 15 | *all* the C++ code. The core safety claim under this new model is that auditing | 
 | 16 | just the C++ side would be sufficient to catch all problems, i.e. the Rust side | 
 | 17 | can be 100% safe. | 
 | 18 |  | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 19 | ```toml | 
 | 20 | [dependencies] | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 21 | cxx = "1.0" | 
| David Tolnay | c5cd7a1 | 2020-09-03 15:32:34 -0700 | [diff] [blame] | 22 |  | 
 | 23 | [build-dependencies] | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 24 | cxx-build = "1.0" | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 25 | ``` | 
 | 26 |  | 
| David Tolnay | 727ea00 | 2020-11-11 11:15:38 -0800 | [diff] [blame] | 27 | *Compiler support: requires rustc 1.48+ and c++11 or newer*<br> | 
| David Tolnay | 5d08baa | 2020-04-27 18:12:08 -0700 | [diff] [blame] | 28 | *[Release notes](https://github.com/dtolnay/cxx/releases)* | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 29 |  | 
 | 30 | <br> | 
 | 31 |  | 
| David Tolnay | 6a936b3 | 2020-11-17 08:32:39 -0800 | [diff] [blame] | 32 | ## Guide | 
 | 33 |  | 
 | 34 | Please see **<https://cxx.rs>** for a tutorial, reference material, and example | 
 | 35 | code. | 
 | 36 |  | 
 | 37 | <br> | 
 | 38 |  | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 39 | ## Overview | 
 | 40 |  | 
 | 41 | The idea is that we define the signatures of both sides of our FFI boundary | 
 | 42 | embedded together in one Rust module (the next section shows an example). From | 
 | 43 | this, CXX receives a complete picture of the boundary to perform static analyses | 
 | 44 | against the types and function signatures to uphold both Rust's and C++'s | 
 | 45 | invariants and requirements. | 
 | 46 |  | 
 | 47 | If everything checks out statically, then CXX uses a pair of code generators to | 
 | 48 | emit the relevant `extern "C"` signatures on both sides together with any | 
 | 49 | necessary static assertions for later in the build process to verify | 
 | 50 | correctness. On the Rust side this code generator is simply an attribute | 
 | 51 | procedural macro. On the C++ side it can be a small Cargo build script if your | 
 | 52 | build is managed by Cargo, or for other build systems like Bazel or Buck we | 
 | 53 | provide a command line tool which generates the header and source file and | 
 | 54 | should be easy to integrate. | 
 | 55 |  | 
 | 56 | The resulting FFI bridge operates at zero or negligible overhead, i.e. no | 
 | 57 | copying, no serialization, no memory allocation, no runtime checks needed. | 
 | 58 |  | 
 | 59 | The FFI signatures are able to use native types from whichever side they please, | 
 | 60 | such as Rust's `String` or C++'s `std::string`, Rust's `Box` or C++'s | 
 | 61 | `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any combination. | 
 | 62 | CXX guarantees an ABI-compatible signature that both sides understand, based on | 
 | 63 | builtin bindings for key standard library types to expose an idiomatic API on | 
 | 64 | those types to the other language. For example when manipulating a C++ string | 
 | 65 | from Rust, its `len()` method becomes a call of the `size()` member function | 
| Christopher Durham | b8d211d | 2020-05-24 11:56:32 -0400 | [diff] [blame] | 66 | defined by C++; when manipulating a Rust string from C++, its `size()` member | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 67 | function calls Rust's `len()`. | 
 | 68 |  | 
 | 69 | <br> | 
 | 70 |  | 
 | 71 | ## Example | 
 | 72 |  | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 73 | In this example we are writing a Rust application that wishes to take advantage | 
 | 74 | of an existing C++ client for a large-file blobstore service. The blobstore | 
 | 75 | supports a `put` operation for a discontiguous buffer upload. For example we | 
 | 76 | might be uploading snapshots of a circular buffer which would tend to consist of | 
 | 77 | 2 chunks, or fragments of a file spread across memory for some other reason. | 
 | 78 |  | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 79 | A runnable version of this example is provided under the *demo* directory of | 
 | 80 | this repo. To try it out, run `cargo run` from that directory. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 81 |  | 
 | 82 | ```rust | 
 | 83 | #[cxx::bridge] | 
 | 84 | mod ffi { | 
 | 85 |     // Any shared structs, whose fields will be visible to both languages. | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 86 |     struct BlobMetadata { | 
 | 87 |         size: usize, | 
 | 88 |         tags: Vec<String>, | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 89 |     } | 
 | 90 |  | 
 | 91 |     extern "Rust" { | 
 | 92 |         // Zero or more opaque types which both languages can pass around but | 
 | 93 |         // only Rust can see the fields. | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 94 |         type MultiBuf; | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 95 |  | 
 | 96 |         // Functions implemented in Rust. | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 97 |         fn next_chunk(buf: &mut MultiBuf) -> &[u8]; | 
 | 98 |     } | 
 | 99 |  | 
| David Tolnay | 7be5b1f | 2020-11-11 10:48:32 -0800 | [diff] [blame] | 100 |     unsafe extern "C++" { | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 101 |         // One or more headers with the matching C++ declarations. Our code | 
 | 102 |         // generators don't read it but it gets #include'd and used in static | 
 | 103 |         // assertions to ensure our picture of the FFI boundary is accurate. | 
 | 104 |         include!("demo/include/blobstore.h"); | 
 | 105 |  | 
 | 106 |         // Zero or more opaque types which both languages can pass around but | 
 | 107 |         // only C++ can see the fields. | 
 | 108 |         type BlobstoreClient; | 
 | 109 |  | 
 | 110 |         // Functions implemented in C++. | 
 | 111 |         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; | 
 | 112 |         fn put(&self, parts: &mut MultiBuf) -> u64; | 
 | 113 |         fn tag(&self, blobid: u64, tag: &str); | 
 | 114 |         fn metadata(&self, blobid: u64) -> BlobMetadata; | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 115 |     } | 
 | 116 | } | 
 | 117 | ``` | 
 | 118 |  | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 119 | Now we simply provide Rust definitions of all the things in the `extern "Rust"` | 
 | 120 | block and C++ definitions of all the things in the `extern "C++"` block, and get | 
 | 121 | to call back and forth safely. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 122 |  | 
 | 123 | Here are links to the complete set of source files involved in the demo: | 
 | 124 |  | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 125 | - [demo/src/main.rs](demo/src/main.rs) | 
 | 126 | - [demo/build.rs](demo/build.rs) | 
| David Tolnay | 4ca366f | 2020-11-10 20:55:31 -0800 | [diff] [blame] | 127 | - [demo/include/blobstore.h](demo/include/blobstore.h) | 
 | 128 | - [demo/src/blobstore.cc](demo/src/blobstore.cc) | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 129 |  | 
 | 130 | To look at the code generated in both languages for the example by the CXX code | 
 | 131 | generators: | 
 | 132 |  | 
 | 133 | ```console | 
 | 134 |    # run Rust code generator and print to stdout | 
 | 135 |    # (requires https://github.com/dtolnay/cargo-expand) | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 136 | $ cargo expand --manifest-path demo/Cargo.toml | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 137 |  | 
 | 138 |    # run C++ code generator and print to stdout | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 139 | $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 140 | ``` | 
 | 141 |  | 
 | 142 | <br> | 
 | 143 |  | 
 | 144 | ## Details | 
 | 145 |  | 
 | 146 | As seen in the example, the language of the FFI boundary involves 3 kinds of | 
 | 147 | items: | 
 | 148 |  | 
 | 149 | - **Shared structs** — their fields are made visible to both languages. | 
 | 150 |   The definition written within cxx::bridge is the single source of truth. | 
 | 151 |  | 
 | 152 | - **Opaque types** — their fields are secret from the other language. | 
 | 153 |   These cannot be passed across the FFI by value but only behind an indirection, | 
 | 154 |   such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can be a type alias | 
 | 155 |   for an arbitrarily complicated generic language-specific type depending on | 
 | 156 |   your use case. | 
 | 157 |  | 
 | 158 | - **Functions** — implemented in either language, callable from the other | 
 | 159 |   language. | 
 | 160 |  | 
| David Tolnay | 48e98d8 | 2020-11-12 15:28:26 -0800 | [diff] [blame] | 161 | Within the `extern "Rust"` part of the CXX bridge we list the types and | 
 | 162 | functions for which Rust is the source of truth. These all implicitly refer to | 
 | 163 | the `super` module, the parent module of the CXX bridge. You can think of the | 
 | 164 | two items listed in the example above as being like `use super::MultiBuf` and | 
 | 165 | `use super::next_chunk` except re-exported to C++. The parent module will either | 
 | 166 | contain the definitions directly for simple things, or contain the relevant | 
 | 167 | `use` statements to bring them into scope from elsewhere. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 168 |  | 
| David Tolnay | 48e98d8 | 2020-11-12 15:28:26 -0800 | [diff] [blame] | 169 | Within the `extern "C++"` part, we list types and functions for which C++ is the | 
 | 170 | source of truth, as well as the header(s) that declare those APIs. In the future | 
 | 171 | it's possible that this section could be generated bindgen-style from the | 
 | 172 | headers but for now we need the signatures written out; static assertions will | 
 | 173 | verify that they are accurate. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 174 |  | 
 | 175 | Your function implementations themselves, whether in C++ or Rust, *do not* need | 
 | 176 | to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the right shims | 
 | 177 | where necessary to make it all work. | 
 | 178 |  | 
 | 179 | <br> | 
 | 180 |  | 
 | 181 | ## Comparison vs bindgen and cbindgen | 
 | 182 |  | 
 | 183 | Notice that with CXX there is repetition of all the function signatures: they | 
 | 184 | are typed out once where the implementation is defined (in C++ or Rust) and | 
 | 185 | again inside the cxx::bridge module, though compile-time assertions guarantee | 
 | 186 | these are kept in sync. This is different from [bindgen] and [cbindgen] where | 
 | 187 | function signatures are typed by a human once and the tool consumes them in one | 
 | 188 | language and emits them in the other language. | 
 | 189 |  | 
 | 190 | [bindgen]: https://github.com/rust-lang/rust-bindgen | 
 | 191 | [cbindgen]: https://github.com/eqrion/cbindgen/ | 
 | 192 |  | 
 | 193 | This is because CXX fills a somewhat different role. It is a lower level tool | 
 | 194 | than bindgen or cbindgen in a sense; you can think of it as being a replacement | 
 | 195 | for the concept of `extern "C"` signatures as we know them, rather than a | 
 | 196 | replacement for a bindgen. It would be reasonable to build a higher level | 
 | 197 | bindgen-like tool on top of CXX which consumes a C++ header and/or Rust module | 
 | 198 | (and/or IDL like Thrift) as source of truth and generates the cxx::bridge, | 
 | 199 | eliminating the repetition while leveraging the static analysis safety | 
 | 200 | guarantees of CXX. | 
 | 201 |  | 
 | 202 | But note in other ways CXX is higher level than the bindgens, with rich support | 
 | 203 | for common standard library types. Frequently with bindgen when we are dealing | 
 | 204 | with an idiomatic C++ API we would end up manually wrapping that API in C-style | 
 | 205 | raw pointer functions, applying bindgen to get unsafe raw pointer Rust | 
 | 206 | functions, and replicating the API again to expose those idiomatically in Rust. | 
 | 207 | That's a much worse form of repetition because it is unsafe all the way through. | 
 | 208 |  | 
 | 209 | By using a CXX bridge as the shared understanding between the languages, rather | 
 | 210 | than `extern "C"` C-style signatures as the shared understanding, common FFI use | 
 | 211 | cases become expressible using 100% safe code. | 
 | 212 |  | 
 | 213 | It would also be reasonable to mix and match, using CXX bridge for the 95% of | 
 | 214 | your FFI that is straightforward and doing the remaining few oddball signatures | 
 | 215 | the old fashioned way with bindgen and cbindgen, if for some reason CXX's static | 
 | 216 | restrictions get in the way. Please file an issue if you end up taking this | 
 | 217 | approach so that we know what ways it would be worthwhile to make the tool more | 
 | 218 | expressive. | 
 | 219 |  | 
 | 220 | <br> | 
 | 221 |  | 
 | 222 | ## Cargo-based setup | 
 | 223 |  | 
 | 224 | For builds that are orchestrated by Cargo, you will use a build script that runs | 
 | 225 | CXX's C++ code generator and compiles the resulting C++ code along with any | 
 | 226 | other C++ code for your crate. | 
 | 227 |  | 
 | 228 | The canonical build script is as follows. The indicated line returns a | 
 | 229 | [`cc::Build`] instance (from the usual widely used `cc` crate) on which you can | 
 | 230 | set up any additional source files and compiler flags as normal. | 
 | 231 |  | 
 | 232 | [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html | 
 | 233 |  | 
| David Tolnay | cc9ece5 | 2020-04-29 18:57:05 -0700 | [diff] [blame] | 234 | ```toml | 
 | 235 | # Cargo.toml | 
 | 236 |  | 
 | 237 | [build-dependencies] | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 238 | cxx-build = "1.0" | 
| David Tolnay | cc9ece5 | 2020-04-29 18:57:05 -0700 | [diff] [blame] | 239 | ``` | 
 | 240 |  | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 241 | ```rust | 
 | 242 | // build.rs | 
 | 243 |  | 
 | 244 | fn main() { | 
| David Tolnay | f8ed073 | 2020-04-29 12:34:47 -0700 | [diff] [blame] | 245 |     cxx_build::bridge("src/main.rs")  // returns a cc::Build | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 246 |         .file("src/demo.cc") | 
| Philip Craig | 7e14e2e | 2020-05-09 10:42:30 +0100 | [diff] [blame] | 247 |         .flag_if_supported("-std=c++11") | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 248 |         .compile("cxxbridge-demo"); | 
 | 249 |  | 
 | 250 |     println!("cargo:rerun-if-changed=src/main.rs"); | 
| David Tolnay | 278f6fc | 2020-09-01 16:16:57 -0700 | [diff] [blame] | 251 |     println!("cargo:rerun-if-changed=src/demo.cc"); | 
 | 252 |     println!("cargo:rerun-if-changed=include/demo.h"); | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 253 | } | 
 | 254 | ``` | 
 | 255 |  | 
 | 256 | <br> | 
 | 257 |  | 
 | 258 | ## Non-Cargo setup | 
 | 259 |  | 
 | 260 | For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate way of | 
 | 261 | invoking the C++ code generator as a standalone command line tool. The tool is | 
 | 262 | packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the | 
| David Tolnay | d9e789e | 2020-10-08 21:22:04 -0700 | [diff] [blame] | 263 | *gen/cmd* directory of this repo. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 264 |  | 
 | 265 | ```bash | 
 | 266 | $ cargo install cxxbridge-cmd | 
 | 267 |  | 
 | 268 | $ cxxbridge src/main.rs --header > path/to/mybridge.h | 
 | 269 | $ cxxbridge src/main.rs > path/to/mybridge.cc | 
 | 270 | ``` | 
 | 271 |  | 
 | 272 | <br> | 
 | 273 |  | 
 | 274 | ## Safety | 
 | 275 |  | 
 | 276 | Be aware that the design of this library is intentionally restrictive and | 
 | 277 | opinionated! It isn't a goal to be powerful enough to handle arbitrary | 
 | 278 | signatures in either language. Instead this project is about carving out a | 
 | 279 | reasonably expressive set of functionality about which we can make useful safety | 
 | 280 | guarantees today and maybe extend over time. You may find that it takes some | 
 | 281 | practice to use CXX bridge effectively as it won't work in all the ways that you | 
 | 282 | are used to. | 
 | 283 |  | 
 | 284 | Some of the considerations that go into ensuring safety are: | 
 | 285 |  | 
 | 286 | - By design, our paired code generators work together to control both sides of | 
 | 287 |   the FFI boundary. Ordinarily in Rust writing your own `extern "C"` blocks is | 
 | 288 |   unsafe because the Rust compiler has no way to know whether the signatures | 
 | 289 |   you've written actually match the signatures implemented in the other | 
 | 290 |   language. With CXX we achieve that visibility and know what's on the other | 
 | 291 |   side. | 
 | 292 |  | 
 | 293 | - Our static analysis detects and prevents passing types by value that shouldn't | 
 | 294 |   be passed by value from C++ to Rust, for example because they may contain | 
 | 295 |   internal pointers that would be screwed up by Rust's move behavior. | 
 | 296 |  | 
 | 297 | - To many people's surprise, it is possible to have a struct in Rust and a | 
 | 298 |   struct in C++ with exactly the same layout / fields / alignment / everything, | 
 | 299 |   and still not the same ABI when passed by value. This is a longstanding | 
 | 300 |   bindgen bug that leads to segfaults in absolutely correct-looking code | 
 | 301 |   ([rust-lang/rust-bindgen#778]). CXX knows about this and can insert the | 
 | 302 |   necessary zero-cost workaround transparently where needed, so go ahead and | 
 | 303 |   pass your structs by value without worries. This is made possible by owning | 
 | 304 |   both sides of the boundary rather than just one. | 
 | 305 |  | 
 | 306 | - Template instantiations: for example in order to expose a UniquePtr\<T\> type | 
 | 307 |   in Rust backed by a real C++ unique\_ptr, we have a way of using a Rust trait | 
 | 308 |   to connect the behavior back to the template instantiations performed by the | 
 | 309 |   other language. | 
 | 310 |  | 
 | 311 | [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778 | 
 | 312 |  | 
 | 313 | <br> | 
 | 314 |  | 
 | 315 | ## Builtin types | 
 | 316 |  | 
| David Tolnay | 559fbb3 | 2020-03-17 23:32:20 -0700 | [diff] [blame] | 317 | In addition to all the primitive types (i32 <=> int32_t), the following | 
| David Tolnay | 06515f0 | 2020-03-17 23:28:02 -0700 | [diff] [blame] | 318 | common types may be used in the fields of shared structs and the arguments and | 
 | 319 | returns of functions. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 320 |  | 
 | 321 | <table> | 
 | 322 | <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr> | 
| David Tolnay | 750755e | 2020-03-01 13:04:08 -0800 | [diff] [blame] | 323 | <tr><td>String</td><td>rust::String</td><td></td></tr> | 
 | 324 | <tr><td>&str</td><td>rust::Str</td><td></td></tr> | 
| David Tolnay | 5515a9e | 2020-11-25 19:07:54 -0800 | [diff] [blame] | 325 | <tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr> | 
 | 326 | <tr><td>&mut [T]</td><td>rust::Slice<T></td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr> | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 327 | <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr> | 
| David Tolnay | 750755e | 2020-03-01 13:04:08 -0800 | [diff] [blame] | 328 | <tr><td>Box<T></td><td>rust::Box<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 329 | <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr<T></a></td><td>std::unique_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> | 
| David Tolnay | b3b24a1 | 2020-12-01 15:27:43 -0800 | [diff] [blame] | 330 | <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr<T></a></td><td>std::shared_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> | 
| David Tolnay | 1092640 | 2020-11-24 21:34:13 -0800 | [diff] [blame] | 331 | <tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr> | 
| David Tolnay | 347c3d0 | 2020-04-24 16:14:07 -0700 | [diff] [blame] | 332 | <tr><td>Vec<T></td><td>rust::Vec<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> | 
| David Tolnay | bf1000f | 2020-11-16 23:47:01 -0800 | [diff] [blame] | 333 | <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector<T></a></td><td>std::vector<T></td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr> | 
| David Tolnay | addc748 | 2020-03-29 22:19:44 -0700 | [diff] [blame] | 334 | <tr><td>fn(T, U) -> V</td><td>rust::Fn<V(T, U)></td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr> | 
| David Tolnay | 31b5aad | 2020-04-10 19:35:47 -0700 | [diff] [blame] | 335 | <tr><td>Result<T></td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr> | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 336 | </table> | 
 | 337 |  | 
| David Tolnay | 736cbca | 2020-03-11 16:49:18 -0700 | [diff] [blame] | 338 | The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in | 
 | 339 | this repo. You will need to include this header in your C++ code when working | 
 | 340 | with those types. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 341 |  | 
 | 342 | The following types are intended to be supported "soon" but are just not | 
 | 343 | implemented yet. I don't expect any of these to be hard to make work but it's a | 
 | 344 | matter of designing a nice API for each in its non-native language. | 
 | 345 |  | 
 | 346 | <table> | 
 | 347 | <tr><th>name in Rust</th><th>name in C++</th></tr> | 
| David Tolnay | 84f232e | 2020-01-08 12:22:56 -0800 | [diff] [blame] | 348 | <tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> | 
 | 349 | <tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> | 
| David Tolnay | 239d05f | 2020-03-13 01:36:50 -0700 | [diff] [blame] | 350 | <tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr> | 
| David Tolnay | 85487b0 | 2020-08-22 06:13:27 -0700 | [diff] [blame] | 351 | <tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> | 
| David Tolnay | 84f232e | 2020-01-08 12:22:56 -0800 | [diff] [blame] | 352 | <tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> | 
 | 353 | <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr> | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 354 | </table> | 
 | 355 |  | 
 | 356 | <br> | 
 | 357 |  | 
 | 358 | ## Remaining work | 
 | 359 |  | 
 | 360 | This is still early days for CXX; I am releasing it as a minimum viable product | 
| David Tolnay | 3deb2f9 | 2020-04-22 19:16:38 -0700 | [diff] [blame] | 361 | to collect feedback on the direction and invite collaborators. Please check the | 
 | 362 | open issues. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 363 |  | 
| David Tolnay | 9c815df | 2020-09-02 09:54:19 -0700 | [diff] [blame] | 364 | Especially please report issues if you run into trouble building or linking any | 
 | 365 | of this stuff. I'm sure there are ways to make the build aspects friendlier or | 
 | 366 | more robust. | 
| David Tolnay | 7db7369 | 2019-10-20 14:51:12 -0400 | [diff] [blame] | 367 |  | 
 | 368 | Finally, I know more about Rust library design than C++ library design so I | 
 | 369 | would appreciate help making the C++ APIs in this project more idiomatic where | 
 | 370 | anyone has suggestions. | 
 | 371 |  | 
 | 372 | <br> | 
 | 373 |  | 
 | 374 | #### License | 
 | 375 |  | 
 | 376 | <sup> | 
 | 377 | Licensed under either of <a href="LICENSE-APACHE">Apache License, Version | 
 | 378 | 2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. | 
 | 379 | </sup> | 
 | 380 |  | 
 | 381 | <br> | 
 | 382 |  | 
 | 383 | <sub> | 
 | 384 | Unless you explicitly state otherwise, any contribution intentionally submitted | 
 | 385 | for inclusion in this project by you, as defined in the Apache-2.0 license, | 
 | 386 | shall be dual licensed as above, without any additional terms or conditions. | 
 | 387 | </sub> |