489 lines
21 KiB
Rust
489 lines
21 KiB
Rust
|
|
//! [![github]](https://github.com/dtolnay/cxx) [![crates-io]](https://crates.io/crates/cxx) [![docs-rs]](https://docs.rs/cxx)
|
||
|
|
//!
|
||
|
|
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
||
|
|
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
|
||
|
|
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! This library provides a **safe** mechanism for calling C++ code from Rust
|
||
|
|
//! and Rust code from C++, not subject to the many ways that things can go
|
||
|
|
//! wrong when using bindgen or cbindgen to generate unsafe C-style bindings.
|
||
|
|
//!
|
||
|
|
//! This doesn't change the fact that 100% of C++ code is unsafe. When auditing
|
||
|
|
//! a project, you would be on the hook for auditing all the unsafe Rust code
|
||
|
|
//! and *all* the C++ code. The core safety claim under this new model is that
|
||
|
|
//! auditing just the C++ side would be sufficient to catch all problems, i.e.
|
||
|
|
//! the Rust side can be 100% safe.
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! *Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
|
||
|
|
//! *[Release notes](https://github.com/dtolnay/cxx/releases)*
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Guide
|
||
|
|
//!
|
||
|
|
//! Please see **<https://cxx.rs>** for a tutorial, reference material, and
|
||
|
|
//! example code.
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Overview
|
||
|
|
//!
|
||
|
|
//! The idea is that we define the signatures of both sides of our FFI boundary
|
||
|
|
//! embedded together in one Rust module (the next section shows an example).
|
||
|
|
//! From this, CXX receives a complete picture of the boundary to perform static
|
||
|
|
//! analyses against the types and function signatures to uphold both Rust's and
|
||
|
|
//! C++'s invariants and requirements.
|
||
|
|
//!
|
||
|
|
//! If everything checks out statically, then CXX uses a pair of code generators
|
||
|
|
//! to emit the relevant `extern "C"` signatures on both sides together with any
|
||
|
|
//! necessary static assertions for later in the build process to verify
|
||
|
|
//! correctness. On the Rust side this code generator is simply an attribute
|
||
|
|
//! procedural macro. On the C++ side it can be a small Cargo build script if
|
||
|
|
//! your build is managed by Cargo, or for other build systems like Bazel or
|
||
|
|
//! Buck we provide a command line tool which generates the header and source
|
||
|
|
//! file and should be easy to integrate.
|
||
|
|
//!
|
||
|
|
//! The resulting FFI bridge operates at zero or negligible overhead, i.e. no
|
||
|
|
//! copying, no serialization, no memory allocation, no runtime checks needed.
|
||
|
|
//!
|
||
|
|
//! The FFI signatures are able to use native types from whichever side they
|
||
|
|
//! please, such as Rust's `String` or C++'s `std::string`, Rust's `Box` or
|
||
|
|
//! C++'s `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any
|
||
|
|
//! combination. CXX guarantees an ABI-compatible signature that both sides
|
||
|
|
//! understand, based on builtin bindings for key standard library types to
|
||
|
|
//! expose an idiomatic API on those types to the other language. For example
|
||
|
|
//! when manipulating a C++ string from Rust, its `len()` method becomes a call
|
||
|
|
//! of the `size()` member function defined by C++; when manipulation a Rust
|
||
|
|
//! string from C++, its `size()` member function calls Rust's `len()`.
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Example
|
||
|
|
//!
|
||
|
|
//! In this example we are writing a Rust application that wishes to take
|
||
|
|
//! advantage of an existing C++ client for a large-file blobstore service. The
|
||
|
|
//! blobstore supports a `put` operation for a discontiguous buffer upload. For
|
||
|
|
//! example we might be uploading snapshots of a circular buffer which would
|
||
|
|
//! tend to consist of 2 chunks, or fragments of a file spread across memory for
|
||
|
|
//! some other reason.
|
||
|
|
//!
|
||
|
|
//! A runnable version of this example is provided under the *demo* directory of
|
||
|
|
//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
|
||
|
|
//! directory.
|
||
|
|
//!
|
||
|
|
//! ```no_run
|
||
|
|
//! #[cxx::bridge]
|
||
|
|
//! mod ffi {
|
||
|
|
//! // Any shared structs, whose fields will be visible to both languages.
|
||
|
|
//! struct BlobMetadata {
|
||
|
|
//! size: usize,
|
||
|
|
//! tags: Vec<String>,
|
||
|
|
//! }
|
||
|
|
//!
|
||
|
|
//! extern "Rust" {
|
||
|
|
//! // Zero or more opaque types which both languages can pass around but
|
||
|
|
//! // only Rust can see the fields.
|
||
|
|
//! type MultiBuf;
|
||
|
|
//!
|
||
|
|
//! // Functions implemented in Rust.
|
||
|
|
//! fn next_chunk(buf: &mut MultiBuf) -> &[u8];
|
||
|
|
//! }
|
||
|
|
//!
|
||
|
|
//! unsafe extern "C++" {
|
||
|
|
//! // One or more headers with the matching C++ declarations. Our code
|
||
|
|
//! // generators don't read it but it gets #include'd and used in static
|
||
|
|
//! // assertions to ensure our picture of the FFI boundary is accurate.
|
||
|
|
//! include!("demo/include/blobstore.h");
|
||
|
|
//!
|
||
|
|
//! // Zero or more opaque types which both languages can pass around but
|
||
|
|
//! // only C++ can see the fields.
|
||
|
|
//! type BlobstoreClient;
|
||
|
|
//!
|
||
|
|
//! // Functions implemented in C++.
|
||
|
|
//! fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
|
||
|
|
//! fn put(&self, parts: &mut MultiBuf) -> u64;
|
||
|
|
//! fn tag(&self, blobid: u64, tag: &str);
|
||
|
|
//! fn metadata(&self, blobid: u64) -> BlobMetadata;
|
||
|
|
//! }
|
||
|
|
//! }
|
||
|
|
//! #
|
||
|
|
//! # pub struct MultiBuf;
|
||
|
|
//! #
|
||
|
|
//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] {
|
||
|
|
//! # unimplemented!()
|
||
|
|
//! # }
|
||
|
|
//! #
|
||
|
|
//! # fn main() {}
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! Now we simply provide Rust definitions of all the things in the `extern
|
||
|
|
//! "Rust"` block and C++ definitions of all the things in the `extern "C++"`
|
||
|
|
//! block, and get to call back and forth safely.
|
||
|
|
//!
|
||
|
|
//! Here are links to the complete set of source files involved in the demo:
|
||
|
|
//!
|
||
|
|
//! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
|
||
|
|
//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
|
||
|
|
//! - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
|
||
|
|
//! - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
|
||
|
|
//!
|
||
|
|
//! To look at the code generated in both languages for the example by the CXX
|
||
|
|
//! code generators:
|
||
|
|
//!
|
||
|
|
//! ```console
|
||
|
|
//! # run Rust code generator and print to stdout
|
||
|
|
//! # (requires https://github.com/dtolnay/cargo-expand)
|
||
|
|
//! $ cargo expand --manifest-path demo/Cargo.toml
|
||
|
|
//!
|
||
|
|
//! # run C++ code generator and print to stdout
|
||
|
|
//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Details
|
||
|
|
//!
|
||
|
|
//! As seen in the example, the language of the FFI boundary involves 3 kinds of
|
||
|
|
//! items:
|
||
|
|
//!
|
||
|
|
//! - **Shared structs** — their fields are made visible to both
|
||
|
|
//! languages. The definition written within cxx::bridge is the single source
|
||
|
|
//! of truth.
|
||
|
|
//!
|
||
|
|
//! - **Opaque types** — their fields are secret from the other language.
|
||
|
|
//! These cannot be passed across the FFI by value but only behind an
|
||
|
|
//! indirection, such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can
|
||
|
|
//! be a type alias for an arbitrarily complicated generic language-specific
|
||
|
|
//! type depending on your use case.
|
||
|
|
//!
|
||
|
|
//! - **Functions** — implemented in either language, callable from the
|
||
|
|
//! other language.
|
||
|
|
//!
|
||
|
|
//! Within the `extern "Rust"` part of the CXX bridge we list the types and
|
||
|
|
//! functions for which Rust is the source of truth. These all implicitly refer
|
||
|
|
//! to the `super` module, the parent module of the CXX bridge. You can think of
|
||
|
|
//! the two items listed in the example above as being like `use
|
||
|
|
//! super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The
|
||
|
|
//! parent module will either contain the definitions directly for simple
|
||
|
|
//! things, or contain the relevant `use` statements to bring them into scope
|
||
|
|
//! from elsewhere.
|
||
|
|
//!
|
||
|
|
//! Within the `extern "C++"` part, we list types and functions for which C++ is
|
||
|
|
//! the source of truth, as well as the header(s) that declare those APIs. In
|
||
|
|
//! the future it's possible that this section could be generated bindgen-style
|
||
|
|
//! from the headers but for now we need the signatures written out; static
|
||
|
|
//! assertions will verify that they are accurate.
|
||
|
|
//!
|
||
|
|
//! Your function implementations themselves, whether in C++ or Rust, *do not*
|
||
|
|
//! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the
|
||
|
|
//! right shims where necessary to make it all work.
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Comparison vs bindgen and cbindgen
|
||
|
|
//!
|
||
|
|
//! Notice that with CXX there is repetition of all the function signatures:
|
||
|
|
//! they are typed out once where the implementation is defined (in C++ or Rust)
|
||
|
|
//! and again inside the cxx::bridge module, though compile-time assertions
|
||
|
|
//! guarantee these are kept in sync. This is different from [bindgen] and
|
||
|
|
//! [cbindgen] where function signatures are typed by a human once and the tool
|
||
|
|
//! consumes them in one language and emits them in the other language.
|
||
|
|
//!
|
||
|
|
//! [bindgen]: https://github.com/rust-lang/rust-bindgen
|
||
|
|
//! [cbindgen]: https://github.com/eqrion/cbindgen/
|
||
|
|
//!
|
||
|
|
//! This is because CXX fills a somewhat different role. It is a lower level
|
||
|
|
//! tool than bindgen or cbindgen in a sense; you can think of it as being a
|
||
|
|
//! replacement for the concept of `extern "C"` signatures as we know them,
|
||
|
|
//! rather than a replacement for a bindgen. It would be reasonable to build a
|
||
|
|
//! higher level bindgen-like tool on top of CXX which consumes a C++ header
|
||
|
|
//! and/or Rust module (and/or IDL like Thrift) as source of truth and generates
|
||
|
|
//! the cxx::bridge, eliminating the repetition while leveraging the static
|
||
|
|
//! analysis safety guarantees of CXX.
|
||
|
|
//!
|
||
|
|
//! But note in other ways CXX is higher level than the bindgens, with rich
|
||
|
|
//! support for common standard library types. Frequently with bindgen when we
|
||
|
|
//! are dealing with an idiomatic C++ API we would end up manually wrapping that
|
||
|
|
//! API in C-style raw pointer functions, applying bindgen to get unsafe raw
|
||
|
|
//! pointer Rust functions, and replicating the API again to expose those
|
||
|
|
//! idiomatically in Rust. That's a much worse form of repetition because it is
|
||
|
|
//! unsafe all the way through.
|
||
|
|
//!
|
||
|
|
//! By using a CXX bridge as the shared understanding between the languages,
|
||
|
|
//! rather than `extern "C"` C-style signatures as the shared understanding,
|
||
|
|
//! common FFI use cases become expressible using 100% safe code.
|
||
|
|
//!
|
||
|
|
//! It would also be reasonable to mix and match, using CXX bridge for the 95%
|
||
|
|
//! of your FFI that is straightforward and doing the remaining few oddball
|
||
|
|
//! signatures the old fashioned way with bindgen and cbindgen, if for some
|
||
|
|
//! reason CXX's static restrictions get in the way. Please file an issue if you
|
||
|
|
//! end up taking this approach so that we know what ways it would be worthwhile
|
||
|
|
//! to make the tool more expressive.
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Cargo-based setup
|
||
|
|
//!
|
||
|
|
//! For builds that are orchestrated by Cargo, you will use a build script that
|
||
|
|
//! runs CXX's C++ code generator and compiles the resulting C++ code along with
|
||
|
|
//! any other C++ code for your crate.
|
||
|
|
//!
|
||
|
|
//! The canonical build script is as follows. The indicated line returns a
|
||
|
|
//! [`cc::Build`] instance (from the usual widely used `cc` crate) on which you
|
||
|
|
//! can set up any additional source files and compiler flags as normal.
|
||
|
|
//!
|
||
|
|
//! [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
|
||
|
|
//!
|
||
|
|
//! ```toml
|
||
|
|
//! # Cargo.toml
|
||
|
|
//!
|
||
|
|
//! [build-dependencies]
|
||
|
|
//! cxx-build = "1.0"
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! ```no_run
|
||
|
|
//! // build.rs
|
||
|
|
//!
|
||
|
|
//! fn main() {
|
||
|
|
//! cxx_build::bridge("src/main.rs") // returns a cc::Build
|
||
|
|
//! .file("src/demo.cc")
|
||
|
|
//! .flag_if_supported("-std=c++11")
|
||
|
|
//! .compile("cxxbridge-demo");
|
||
|
|
//!
|
||
|
|
//! println!("cargo:rerun-if-changed=src/main.rs");
|
||
|
|
//! println!("cargo:rerun-if-changed=src/demo.cc");
|
||
|
|
//! println!("cargo:rerun-if-changed=include/demo.h");
|
||
|
|
//! }
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! <br><br>
|
||
|
|
//!
|
||
|
|
//! # Non-Cargo setup
|
||
|
|
//!
|
||
|
|
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
|
||
|
|
//! way of invoking the C++ code generator as a standalone command line tool.
|
||
|
|
//! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
|
||
|
|
//! built from the *gen/cmd* directory of <https://github.com/dtolnay/cxx>.
|
||
|
|
//!
|
||
|
|
//! ```bash
|
||
|
|
//! $ cargo install cxxbridge-cmd
|
||
|
|
//!
|
||
|
|
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
|
||
|
|
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
|
||
|
|
//! ```
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Safety
|
||
|
|
//!
|
||
|
|
//! Be aware that the design of this library is intentionally restrictive and
|
||
|
|
//! opinionated! It isn't a goal to be powerful enough to handle arbitrary
|
||
|
|
//! signatures in either language. Instead this project is about carving out a
|
||
|
|
//! reasonably expressive set of functionality about which we can make useful
|
||
|
|
//! safety guarantees today and maybe extend over time. You may find that it
|
||
|
|
//! takes some practice to use CXX bridge effectively as it won't work in all
|
||
|
|
//! the ways that you are used to.
|
||
|
|
//!
|
||
|
|
//! Some of the considerations that go into ensuring safety are:
|
||
|
|
//!
|
||
|
|
//! - By design, our paired code generators work together to control both sides
|
||
|
|
//! of the FFI boundary. Ordinarily in Rust writing your own `extern "C"`
|
||
|
|
//! blocks is unsafe because the Rust compiler has no way to know whether the
|
||
|
|
//! signatures you've written actually match the signatures implemented in the
|
||
|
|
//! other language. With CXX we achieve that visibility and know what's on the
|
||
|
|
//! other side.
|
||
|
|
//!
|
||
|
|
//! - Our static analysis detects and prevents passing types by value that
|
||
|
|
//! shouldn't be passed by value from C++ to Rust, for example because they
|
||
|
|
//! may contain internal pointers that would be screwed up by Rust's move
|
||
|
|
//! behavior.
|
||
|
|
//!
|
||
|
|
//! - To many people's surprise, it is possible to have a struct in Rust and a
|
||
|
|
//! struct in C++ with exactly the same layout / fields / alignment /
|
||
|
|
//! everything, and still not the same ABI when passed by value. This is a
|
||
|
|
//! longstanding bindgen bug that leads to segfaults in absolutely
|
||
|
|
//! correct-looking code ([rust-lang/rust-bindgen#778]). CXX knows about this
|
||
|
|
//! and can insert the necessary zero-cost workaround transparently where
|
||
|
|
//! needed, so go ahead and pass your structs by value without worries. This
|
||
|
|
//! is made possible by owning both sides of the boundary rather than just
|
||
|
|
//! one.
|
||
|
|
//!
|
||
|
|
//! - Template instantiations: for example in order to expose a UniquePtr\<T\>
|
||
|
|
//! type in Rust backed by a real C++ unique\_ptr, we have a way of using a
|
||
|
|
//! Rust trait to connect the behavior back to the template instantiations
|
||
|
|
//! performed by the other language.
|
||
|
|
//!
|
||
|
|
//! [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
|
||
|
|
//!
|
||
|
|
//! <br>
|
||
|
|
//!
|
||
|
|
//! # Builtin types
|
||
|
|
//!
|
||
|
|
//! In addition to all the primitive types (i32 <=> int32_t), the
|
||
|
|
//! following common types may be used in the fields of shared structs and the
|
||
|
|
//! arguments and returns of functions.
|
||
|
|
//!
|
||
|
|
//! <table>
|
||
|
|
//! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
|
||
|
|
//! <tr><td>String</td><td>rust::String</td><td></td></tr>
|
||
|
|
//! <tr><td>&str</td><td>rust::Str</td><td></td></tr>
|
||
|
|
//! <tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
|
||
|
|
//! <tr><td>&mut [T]</td><td>rust::Slice<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
|
||
|
|
//! <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>
|
||
|
|
//! <tr><td>Box<T></td><td>rust::Box<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
|
||
|
|
//! <tr><td><a href="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>
|
||
|
|
//! <tr><td><a href="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>
|
||
|
|
//! <tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
|
||
|
|
//! <tr><td>Vec<T></td><td>rust::Vec<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
|
||
|
|
//! <tr><td><a href="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>
|
||
|
|
//! <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>
|
||
|
|
//! <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>
|
||
|
|
//! <tr><td>Result<T></td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
|
||
|
|
//! </table>
|
||
|
|
//!
|
||
|
|
//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
|
||
|
|
//! in <https://github.com/dtolnay/cxx>. You will need to include this header in
|
||
|
|
//! your C++ code when working with those types.
|
||
|
|
//!
|
||
|
|
//! The following types are intended to be supported "soon" but are just not
|
||
|
|
//! implemented yet. I don't expect any of these to be hard to make work but
|
||
|
|
//! it's a matter of designing a nice API for each in its non-native language.
|
||
|
|
//!
|
||
|
|
//! <table>
|
||
|
|
//! <tr><th>name in Rust</th><th>name in C++</th></tr>
|
||
|
|
//! <tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
|
||
|
|
//! <tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr>
|
||
|
|
//! <tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr>
|
||
|
|
//! <tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr>
|
||
|
|
//! <tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr>
|
||
|
|
//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr>
|
||
|
|
//! </table>
|
||
|
|
|
||
|
|
#![no_std]
|
||
|
|
#![doc(html_root_url = "https://docs.rs/cxx/1.0.42")]
|
||
|
|
#![deny(improper_ctypes)]
|
||
|
|
#![allow(non_camel_case_types)]
|
||
|
|
#![allow(
|
||
|
|
clippy::cognitive_complexity,
|
||
|
|
clippy::declare_interior_mutable_const,
|
||
|
|
clippy::doc_markdown,
|
||
|
|
clippy::empty_enum,
|
||
|
|
clippy::inherent_to_string,
|
||
|
|
clippy::items_after_statements,
|
||
|
|
clippy::large_enum_variant,
|
||
|
|
clippy::len_without_is_empty,
|
||
|
|
clippy::missing_errors_doc,
|
||
|
|
clippy::missing_safety_doc,
|
||
|
|
clippy::module_inception,
|
||
|
|
clippy::module_name_repetitions,
|
||
|
|
clippy::must_use_candidate,
|
||
|
|
clippy::needless_doctest_main,
|
||
|
|
clippy::new_without_default,
|
||
|
|
clippy::or_fun_call,
|
||
|
|
clippy::ptr_arg,
|
||
|
|
clippy::toplevel_ref_arg,
|
||
|
|
clippy::useless_let_if_seq,
|
||
|
|
clippy::wrong_self_convention
|
||
|
|
)]
|
||
|
|
|
||
|
|
#[cfg(built_with_cargo)]
|
||
|
|
extern crate link_cplusplus;
|
||
|
|
|
||
|
|
extern crate alloc;
|
||
|
|
extern crate self as cxx;
|
||
|
|
extern crate std;
|
||
|
|
|
||
|
|
#[macro_use]
|
||
|
|
mod macros;
|
||
|
|
|
||
|
|
mod cxx_vector;
|
||
|
|
mod exception;
|
||
|
|
mod extern_type;
|
||
|
|
mod fmt;
|
||
|
|
mod function;
|
||
|
|
pub mod memory;
|
||
|
|
mod opaque;
|
||
|
|
mod result;
|
||
|
|
mod rust_slice;
|
||
|
|
mod rust_str;
|
||
|
|
mod rust_string;
|
||
|
|
mod rust_type;
|
||
|
|
mod rust_vec;
|
||
|
|
mod shared_ptr;
|
||
|
|
#[path = "cxx_string.rs"]
|
||
|
|
mod string;
|
||
|
|
mod symbols;
|
||
|
|
mod type_id;
|
||
|
|
mod unique_ptr;
|
||
|
|
mod unwind;
|
||
|
|
pub mod vector;
|
||
|
|
mod weak_ptr;
|
||
|
|
|
||
|
|
pub use crate::cxx_vector::CxxVector;
|
||
|
|
pub use crate::exception::Exception;
|
||
|
|
pub use crate::extern_type::{kind, ExternType};
|
||
|
|
pub use crate::shared_ptr::SharedPtr;
|
||
|
|
pub use crate::string::CxxString;
|
||
|
|
pub use crate::unique_ptr::UniquePtr;
|
||
|
|
pub use crate::weak_ptr::WeakPtr;
|
||
|
|
pub use cxxbridge_macro::bridge;
|
||
|
|
|
||
|
|
/// Synonym for `CxxString`.
|
||
|
|
///
|
||
|
|
/// To avoid confusion with Rust's standard library string you probably
|
||
|
|
/// shouldn't import this type with `use`. Instead, write `cxx::String`, or
|
||
|
|
/// import and use `CxxString`.
|
||
|
|
pub type String = CxxString;
|
||
|
|
|
||
|
|
/// Synonym for `CxxVector`.
|
||
|
|
///
|
||
|
|
/// To avoid confusion with Rust's standard library vector you probably
|
||
|
|
/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or
|
||
|
|
/// import and use `CxxVector`.
|
||
|
|
pub type Vector<T> = CxxVector<T>;
|
||
|
|
|
||
|
|
// Not public API.
|
||
|
|
#[doc(hidden)]
|
||
|
|
pub mod private {
|
||
|
|
pub use crate::cxx_vector::VectorElement;
|
||
|
|
pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
|
||
|
|
pub use crate::function::FatFunction;
|
||
|
|
pub use crate::opaque::Opaque;
|
||
|
|
pub use crate::result::{r#try, Result};
|
||
|
|
pub use crate::rust_slice::RustSlice;
|
||
|
|
pub use crate::rust_str::RustStr;
|
||
|
|
pub use crate::rust_string::RustString;
|
||
|
|
pub use crate::rust_type::{ImplBox, ImplVec, RustType};
|
||
|
|
pub use crate::rust_vec::RustVec;
|
||
|
|
pub use crate::shared_ptr::SharedPtrTarget;
|
||
|
|
pub use crate::string::StackString;
|
||
|
|
pub use crate::unique_ptr::UniquePtrTarget;
|
||
|
|
pub use crate::unwind::catch_unwind;
|
||
|
|
pub use crate::weak_ptr::WeakPtrTarget;
|
||
|
|
pub use cxxbridge_macro::type_id;
|
||
|
|
}
|
||
|
|
|
||
|
|
mod actually_private {
|
||
|
|
pub trait Private {}
|
||
|
|
}
|
||
|
|
|
||
|
|
macro_rules! chars {
|
||
|
|
($($ch:ident)*) => {
|
||
|
|
$(
|
||
|
|
#[doc(hidden)]
|
||
|
|
pub enum $ch {}
|
||
|
|
)*
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
chars! {
|
||
|
|
_0 _1 _2 _3 _4 _5 _6 _7 _8 _9
|
||
|
|
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
|
||
|
|
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
|
||
|
|
__ // underscore
|
||
|
|
}
|