cxx/
lib.rs

1//! [![github]](https://github.com/dtolnay/cxx) [![crates-io]](https://crates.io/crates/cxx) [![docs-rs]](https://docs.rs/cxx)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! This library provides a **safe** mechanism for calling C++ code from Rust
10//! and Rust code from C++, not subject to the many ways that things can go
11//! wrong when using bindgen or cbindgen to generate unsafe C-style bindings.
12//!
13//! This doesn't change the fact that 100% of C++ code is unsafe. When auditing
14//! a project, you would be on the hook for auditing all the unsafe Rust code
15//! and *all* the C++ code. The core safety claim under this new model is that
16//! auditing just the C++ side would be sufficient to catch all problems, i.e.
17//! the Rust side can be 100% safe.
18//!
19//! <br>
20//!
21//! *Compiler support: requires rustc 1.63+ and c++11 or newer*<br>
22//! *[Release notes](https://github.com/dtolnay/cxx/releases)*
23//!
24//! <br>
25//!
26//! # Guide
27//!
28//! Please see **<https://cxx.rs>** for a tutorial, reference material, and
29//! example code.
30//!
31//! <br>
32//!
33//! # Overview
34//!
35//! The idea is that we define the signatures of both sides of our FFI boundary
36//! embedded together in one Rust module (the next section shows an example).
37//! From this, CXX receives a complete picture of the boundary to perform static
38//! analyses against the types and function signatures to uphold both Rust's and
39//! C++'s invariants and requirements.
40//!
41//! If everything checks out statically, then CXX uses a pair of code generators
42//! to emit the relevant `extern "C"` signatures on both sides together with any
43//! necessary static assertions for later in the build process to verify
44//! correctness. On the Rust side this code generator is simply an attribute
45//! procedural macro. On the C++ side it can be a small Cargo build script if
46//! your build is managed by Cargo, or for other build systems like Bazel or
47//! Buck we provide a command line tool which generates the header and source
48//! file and should be easy to integrate.
49//!
50//! The resulting FFI bridge operates at zero or negligible overhead, i.e. no
51//! copying, no serialization, no memory allocation, no runtime checks needed.
52//!
53//! The FFI signatures are able to use native types from whichever side they
54//! please, such as Rust's `String` or C++'s `std::string`, Rust's `Box` or
55//! C++'s `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any
56//! combination. CXX guarantees an ABI-compatible signature that both sides
57//! understand, based on builtin bindings for key standard library types to
58//! expose an idiomatic API on those types to the other language. For example
59//! when manipulating a C++ string from Rust, its `len()` method becomes a call
60//! of the `size()` member function defined by C++; when manipulation a Rust
61//! string from C++, its `size()` member function calls Rust's `len()`.
62//!
63//! <br>
64//!
65//! # Example
66//!
67//! In this example we are writing a Rust application that wishes to take
68//! advantage of an existing C++ client for a large-file blobstore service. The
69//! blobstore supports a `put` operation for a discontiguous buffer upload. For
70//! example we might be uploading snapshots of a circular buffer which would
71//! tend to consist of 2 chunks, or fragments of a file spread across memory for
72//! some other reason.
73//!
74//! A runnable version of this example is provided under the *demo* directory of
75//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
76//! directory.
77//!
78//! ```no_run
79//! #[cxx::bridge]
80//! mod ffi {
81//!     // Any shared structs, whose fields will be visible to both languages.
82//!     struct BlobMetadata {
83//!         size: usize,
84//!         tags: Vec<String>,
85//!     }
86//!
87//!     extern "Rust" {
88//!         // Zero or more opaque types which both languages can pass around but
89//!         // only Rust can see the fields.
90//!         type MultiBuf;
91//!
92//!         // Functions implemented in Rust.
93//!         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
94//!     }
95//!
96//!     unsafe extern "C++" {
97//!         // One or more headers with the matching C++ declarations. Our code
98//!         // generators don't read it but it gets #include'd and used in static
99//!         // assertions to ensure our picture of the FFI boundary is accurate.
100//!         include!("demo/include/blobstore.h");
101//!
102//!         // Zero or more opaque types which both languages can pass around but
103//!         // only C++ can see the fields.
104//!         type BlobstoreClient;
105//!
106//!         // Functions implemented in C++.
107//!         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
108//!         fn put(&self, parts: &mut MultiBuf) -> u64;
109//!         fn tag(&self, blobid: u64, tag: &str);
110//!         fn metadata(&self, blobid: u64) -> BlobMetadata;
111//!     }
112//! }
113//! #
114//! # pub struct MultiBuf;
115//! #
116//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] {
117//! #     unimplemented!()
118//! # }
119//! #
120//! # fn main() {}
121//! ```
122//!
123//! Now we simply provide Rust definitions of all the things in the `extern
124//! "Rust"` block and C++ definitions of all the things in the `extern "C++"`
125//! block, and get to call back and forth safely.
126//!
127//! Here are links to the complete set of source files involved in the demo:
128//!
129//! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
130//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
131//! - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
132//! - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
133//!
134//! To look at the code generated in both languages for the example by the CXX
135//! code generators:
136//!
137//! ```console
138//!    # run Rust code generator and print to stdout
139//!    # (requires https://github.com/dtolnay/cargo-expand)
140//! $ cargo expand --manifest-path demo/Cargo.toml
141//!
142//!    # run C++ code generator and print to stdout
143//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
144//! ```
145//!
146//! <br>
147//!
148//! # Details
149//!
150//! As seen in the example, the language of the FFI boundary involves 3 kinds of
151//! items:
152//!
153//! - **Shared structs** &mdash; their fields are made visible to both
154//!   languages. The definition written within cxx::bridge is the single source
155//!   of truth.
156//!
157//! - **Opaque types** &mdash; their fields are secret from the other language.
158//!   These cannot be passed across the FFI by value but only behind an
159//!   indirection, such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can
160//!   be a type alias for an arbitrarily complicated generic language-specific
161//!   type depending on your use case.
162//!
163//! - **Functions** &mdash; implemented in either language, callable from the
164//!   other language.
165//!
166//! Within the `extern "Rust"` part of the CXX bridge we list the types and
167//! functions for which Rust is the source of truth. These all implicitly refer
168//! to the `super` module, the parent module of the CXX bridge. You can think of
169//! the two items listed in the example above as being like `use
170//! super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The
171//! parent module will either contain the definitions directly for simple
172//! things, or contain the relevant `use` statements to bring them into scope
173//! from elsewhere.
174//!
175//! Within the `extern "C++"` part, we list types and functions for which C++ is
176//! the source of truth, as well as the header(s) that declare those APIs. In
177//! the future it's possible that this section could be generated bindgen-style
178//! from the headers but for now we need the signatures written out; static
179//! assertions will verify that they are accurate.
180//!
181//! Your function implementations themselves, whether in C++ or Rust, *do not*
182//! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the
183//! right shims where necessary to make it all work.
184//!
185//! <br>
186//!
187//! # Comparison vs bindgen and cbindgen
188//!
189//! Notice that with CXX there is repetition of all the function signatures:
190//! they are typed out once where the implementation is defined (in C++ or Rust)
191//! and again inside the cxx::bridge module, though compile-time assertions
192//! guarantee these are kept in sync. This is different from [bindgen] and
193//! [cbindgen] where function signatures are typed by a human once and the tool
194//! consumes them in one language and emits them in the other language.
195//!
196//! [bindgen]: https://github.com/rust-lang/rust-bindgen
197//! [cbindgen]: https://github.com/eqrion/cbindgen/
198//!
199//! This is because CXX fills a somewhat different role. It is a lower level
200//! tool than bindgen or cbindgen in a sense; you can think of it as being a
201//! replacement for the concept of `extern "C"` signatures as we know them,
202//! rather than a replacement for a bindgen. It would be reasonable to build a
203//! higher level bindgen-like tool on top of CXX which consumes a C++ header
204//! and/or Rust module (and/or IDL like Thrift) as source of truth and generates
205//! the cxx::bridge, eliminating the repetition while leveraging the static
206//! analysis safety guarantees of CXX.
207//!
208//! But note in other ways CXX is higher level than the bindgens, with rich
209//! support for common standard library types. Frequently with bindgen when we
210//! are dealing with an idiomatic C++ API we would end up manually wrapping that
211//! API in C-style raw pointer functions, applying bindgen to get unsafe raw
212//! pointer Rust functions, and replicating the API again to expose those
213//! idiomatically in Rust. That's a much worse form of repetition because it is
214//! unsafe all the way through.
215//!
216//! By using a CXX bridge as the shared understanding between the languages,
217//! rather than `extern "C"` C-style signatures as the shared understanding,
218//! common FFI use cases become expressible using 100% safe code.
219//!
220//! It would also be reasonable to mix and match, using CXX bridge for the 95%
221//! of your FFI that is straightforward and doing the remaining few oddball
222//! signatures the old fashioned way with bindgen and cbindgen, if for some
223//! reason CXX's static restrictions get in the way. Please file an issue if you
224//! end up taking this approach so that we know what ways it would be worthwhile
225//! to make the tool more expressive.
226//!
227//! <br>
228//!
229//! # Cargo-based setup
230//!
231//! For builds that are orchestrated by Cargo, you will use a build script that
232//! runs CXX's C++ code generator and compiles the resulting C++ code along with
233//! any other C++ code for your crate.
234//!
235//! The canonical build script is as follows. The indicated line returns a
236//! [`cc::Build`] instance (from the usual widely used `cc` crate) on which you
237//! can set up any additional source files and compiler flags as normal.
238//!
239//! [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
240//!
241//! ```toml
242//! # Cargo.toml
243//!
244//! [build-dependencies]
245//! cxx-build = "1.0"
246//! ```
247//!
248//! ```no_run
249//! // build.rs
250//!
251//! fn main() {
252//!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
253//!         .file("src/demo.cc")
254//!         .std("c++11")
255//!         .compile("cxxbridge-demo");
256//!
257//!     println!("cargo:rerun-if-changed=src/main.rs");
258//!     println!("cargo:rerun-if-changed=src/demo.cc");
259//!     println!("cargo:rerun-if-changed=include/demo.h");
260//! }
261//! ```
262//!
263//! <br><br>
264//!
265//! # Non-Cargo setup
266//!
267//! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
268//! way of invoking the C++ code generator as a standalone command line tool.
269//! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
270//! built from the *gen/cmd* directory of <https://github.com/dtolnay/cxx>.
271//!
272//! ```bash
273//! $ cargo install cxxbridge-cmd
274//!
275//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
276//! $ cxxbridge src/main.rs > path/to/mybridge.cc
277//! ```
278//!
279//! <br>
280//!
281//! # Safety
282//!
283//! Be aware that the design of this library is intentionally restrictive and
284//! opinionated! It isn't a goal to be powerful enough to handle arbitrary
285//! signatures in either language. Instead this project is about carving out a
286//! reasonably expressive set of functionality about which we can make useful
287//! safety guarantees today and maybe extend over time. You may find that it
288//! takes some practice to use CXX bridge effectively as it won't work in all
289//! the ways that you are used to.
290//!
291//! Some of the considerations that go into ensuring safety are:
292//!
293//! - By design, our paired code generators work together to control both sides
294//!   of the FFI boundary. Ordinarily in Rust writing your own `extern "C"`
295//!   blocks is unsafe because the Rust compiler has no way to know whether the
296//!   signatures you've written actually match the signatures implemented in the
297//!   other language. With CXX we achieve that visibility and know what's on the
298//!   other side.
299//!
300//! - Our static analysis detects and prevents passing types by value that
301//!   shouldn't be passed by value from C++ to Rust, for example because they
302//!   may contain internal pointers that would be screwed up by Rust's move
303//!   behavior.
304//!
305//! - To many people's surprise, it is possible to have a struct in Rust and a
306//!   struct in C++ with exactly the same layout / fields / alignment /
307//!   everything, and still not the same ABI when passed by value. This is a
308//!   longstanding bindgen bug that leads to segfaults in absolutely
309//!   correct-looking code ([rust-lang/rust-bindgen#778]). CXX knows about this
310//!   and can insert the necessary zero-cost workaround transparently where
311//!   needed, so go ahead and pass your structs by value without worries. This
312//!   is made possible by owning both sides of the boundary rather than just
313//!   one.
314//!
315//! - Template instantiations: for example in order to expose a UniquePtr\<T\>
316//!   type in Rust backed by a real C++ unique\_ptr, we have a way of using a
317//!   Rust trait to connect the behavior back to the template instantiations
318//!   performed by the other language.
319//!
320//! [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
321//!
322//! <br>
323//!
324//! # Builtin types
325//!
326//! In addition to all the primitive types (i32 &lt;=&gt; int32_t), the
327//! following common types may be used in the fields of shared structs and the
328//! arguments and returns of functions.
329//!
330//! <table>
331//! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
332//! <tr><td>String</td><td>rust::String</td><td></td></tr>
333//! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
334//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
335//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
336//! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
337//! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
338//! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
339//! <tr><td><a href="struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
340//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
341//! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
342//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
343//! <tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
344//! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
345//! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
346//! </table>
347//!
348//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
349//! in <https://github.com/dtolnay/cxx>. You will need to include this header in
350//! your C++ code when working with those types.
351//!
352//! The following types are intended to be supported "soon" but are just not
353//! implemented yet. I don't expect any of these to be hard to make work but
354//! it's a matter of designing a nice API for each in its non-native language.
355//!
356//! <table>
357//! <tr><th>name in Rust</th><th>name in C++</th></tr>
358//! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
359//! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
360//! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
361//! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
362//! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
363//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
364//! </table>
365
366#![no_std]
367#![doc(html_root_url = "https://docs.rs/cxx/1.0.122")]
368#![cfg_attr(doc_cfg, feature(doc_cfg))]
369#![deny(
370    improper_ctypes,
371    improper_ctypes_definitions,
372    missing_docs,
373    unsafe_op_in_unsafe_fn
374)]
375#![warn(
376    clippy::alloc_instead_of_core,
377    clippy::std_instead_of_alloc,
378    clippy::std_instead_of_core
379)]
380#![allow(non_camel_case_types)]
381#![allow(
382    clippy::cast_possible_truncation,
383    clippy::cognitive_complexity,
384    clippy::declare_interior_mutable_const,
385    clippy::doc_markdown,
386    clippy::duplicated_attributes, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/12537
387    clippy::empty_enum,
388    clippy::extra_unused_type_parameters,
389    clippy::inherent_to_string,
390    clippy::items_after_statements,
391    clippy::large_enum_variant,
392    clippy::len_without_is_empty,
393    clippy::missing_errors_doc,
394    clippy::missing_safety_doc,
395    clippy::module_inception,
396    clippy::module_name_repetitions,
397    clippy::must_use_candidate,
398    clippy::needless_doctest_main,
399    clippy::new_without_default,
400    clippy::or_fun_call,
401    clippy::ptr_arg,
402    clippy::ptr_as_ptr,
403    clippy::toplevel_ref_arg,
404    clippy::transmute_undefined_repr, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8417
405    clippy::uninlined_format_args,
406    clippy::useless_let_if_seq,
407)]
408
409#[cfg(built_with_cargo)]
410extern crate link_cplusplus;
411
412extern crate self as cxx;
413
414#[doc(hidden)]
415pub extern crate core;
416
417#[cfg(feature = "alloc")]
418#[doc(hidden)]
419pub extern crate alloc;
420
421#[cfg(not(feature = "alloc"))]
422extern crate core as alloc;
423
424#[cfg(feature = "std")]
425#[doc(hidden)]
426pub extern crate std;
427
428// Block inadvertent use of items from libstd, which does not otherwise produce
429// a compile-time error on edition 2018+.
430#[cfg(not(feature = "std"))]
431extern crate core as std;
432
433#[cfg(not(any(feature = "alloc", cxx_experimental_no_alloc)))]
434compile_error! {
435    r#"cxx support for no_alloc is incomplete and semver exempt; you must build with at least one of feature="std", feature="alloc", or RUSTFLAGS='--cfg cxx_experimental_no_alloc'"#
436}
437
438#[cfg(all(compile_error_if_alloc, feature = "alloc"))]
439compile_error! {
440    r#"feature="alloc" is unexpectedly enabled"#
441}
442
443#[cfg(all(compile_error_if_std, feature = "std"))]
444compile_error! {
445    r#"feature="std" is unexpectedly enabled"#
446}
447
448#[macro_use]
449mod macros;
450
451mod c_char;
452mod cxx_vector;
453mod exception;
454mod extern_type;
455mod fmt;
456mod function;
457mod hash;
458mod lossy;
459pub mod memory;
460mod opaque;
461mod result;
462mod rust_slice;
463mod rust_str;
464mod rust_string;
465mod rust_type;
466mod rust_vec;
467mod shared_ptr;
468mod sip;
469#[path = "cxx_string.rs"]
470mod string;
471mod symbols;
472mod type_id;
473mod unique_ptr;
474mod unwind;
475pub mod vector;
476mod weak_ptr;
477
478pub use crate::cxx_vector::CxxVector;
479#[cfg(feature = "alloc")]
480#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
481pub use crate::exception::Exception;
482pub use crate::extern_type::{kind, ExternType};
483pub use crate::shared_ptr::SharedPtr;
484pub use crate::string::CxxString;
485pub use crate::unique_ptr::UniquePtr;
486pub use crate::weak_ptr::WeakPtr;
487pub use cxxbridge_macro::bridge;
488
489/// Synonym for `CxxString`.
490///
491/// To avoid confusion with Rust's standard library string you probably
492/// shouldn't import this type with `use`. Instead, write `cxx::String`, or
493/// import and use `CxxString`.
494pub type String = CxxString;
495
496/// Synonym for `CxxVector`.
497///
498/// To avoid confusion with Rust's standard library vector you probably
499/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or
500/// import and use `CxxVector`.
501pub type Vector<T> = CxxVector<T>;
502
503// Not public API.
504#[doc(hidden)]
505pub mod private {
506    pub use crate::c_char::c_char;
507    pub use crate::cxx_vector::VectorElement;
508    pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
509    pub use crate::function::FatFunction;
510    pub use crate::hash::hash;
511    pub use crate::opaque::Opaque;
512    #[cfg(feature = "alloc")]
513    pub use crate::result::{r#try, Result};
514    pub use crate::rust_slice::RustSlice;
515    pub use crate::rust_str::RustStr;
516    #[cfg(feature = "alloc")]
517    pub use crate::rust_string::RustString;
518    pub use crate::rust_type::{ImplBox, ImplVec, RustType};
519    #[cfg(feature = "alloc")]
520    pub use crate::rust_vec::RustVec;
521    pub use crate::shared_ptr::SharedPtrTarget;
522    pub use crate::string::StackString;
523    pub use crate::unique_ptr::UniquePtrTarget;
524    pub use crate::unwind::prevent_unwind;
525    pub use crate::weak_ptr::WeakPtrTarget;
526    pub use core::{concat, module_path};
527    pub use cxxbridge_macro::type_id;
528}
529
530mod actually_private {
531    pub trait Private {}
532}
533
534macro_rules! chars {
535    ($($ch:ident)*) => {
536        $(
537            #[doc(hidden)]
538            pub enum $ch {}
539        )*
540    };
541}
542
543chars! {
544    _0 _1 _2 _3 _4 _5 _6 _7 _8 _9
545    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
546    a b c d e f g h i j k l m n o p q r s t u v w x y z
547    __ // underscore
548}
549
550#[repr(transparent)]
551struct void(#[allow(dead_code)] core::ffi::c_void);