### Console Test for JSON Prettification Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/slice.md Demonstrates how to run the C++ and Rust example from the command line, showing the input JSON and the pretty-printed output. ```console $ echo '{"fearless":"concurrency"}' | cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/example` { "fearless": "concurrency" } ``` -------------------------------- ### Example: Pretty-printing JSON with Rust and C++ Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/slice.md This example demonstrates how to use `rust::Slice` to pass JSON data from C++ to Rust for pretty-printing, then returning the formatted string to C++. ```APIDOC ## Example: Pretty-printing JSON This example is a C++ program that constructs a slice containing JSON data (by reading from stdin, but it could be from anywhere), then calls into Rust to pretty-print that JSON data into a `std::string` via the [serde_json] and [serde_transcode] crates. [serde_json]: https://github.com/serde-rs/json [serde_transcode]: https://github.com/sfackler/serde-transcode ### Rust Code (`src/main.rs`) ```rust #![no_main] // main defined in C++ by main.cc use cxx::CxxString; use std::io::{self, Write}; use std::pin::Pin; #[cxx::bridge] mod ffi { extern "Rust" { fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>; } } struct WriteToCxxString<'a>(Pin<&'a mut CxxString>); impl<'a> Write for WriteToCxxString<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.as_mut().push_bytes(buf); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> { let writer = WriteToCxxString(output); let mut deserializer = serde_json::Deserializer::from_slice(input); let mut serializer = serde_json::Serializer::pretty(writer); serde_transcode::transcode(&mut deserializer, &mut serializer) } ``` ### C++ Code (`src/main.cc`) ```cpp #include "example/src/main.rs.h" #include #include #include #include int main() { // Read json from stdin. std::istreambuf_iterator begin{std::cin}, end; std::vector input{begin, end}; rust::Slice slice{input.data(), input.size()}; // Prettify using serde_json and serde_transcode. std::string output; prettify_json(slice, output); // Write to stdout. std::cout << output << std::endl; } ``` ### Testing the example: ```console $ echo '{"fearless":"concurrency"}' | cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/example` { "fearless": "concurrency" } ``` ``` -------------------------------- ### Bazel BUILD File Example for Rust/C++ Integration Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/bazel.md An example Bazel BUILD file demonstrating how to integrate Rust and C++ code using the `rust_cxx_bridge` Starlark rule. It defines targets for a Rust binary, C++ libraries, and the bridge itself. ```python # demo/BUILD.bazel load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_rust//rust:defs.bzl", "rust_binary") load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") ust_binary( name = "demo", srcs = glob(["src/**/*.rs"]), deps = [ ":blobstore-sys", ":bridge", "//:cxx", ], ) rust_cxx_bridge( name = "bridge", src = "src/main.rs", deps = [":blobstore-include"], ) cc_library( name = "blobstore-sys", srcs = ["src/blobstore.cc"], deps = [ ":blobstore-include", ":bridge/include", ], ) cc_library( name = "blobstore-include", hdrs = ["include/blobstore.h"], deps = ["//:core"], ) ``` -------------------------------- ### Install cxxbridge-cmd Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/bazel.md Install the CXX Rust/C++ bridge command-line tool using Cargo. This tool is essential for generating C++ header and source files from Rust code. ```bash $ cargo install cxxbridge-cmd ``` -------------------------------- ### Console Output of Blobstore Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md The expected output from running the Rust main function, showing the generated blobid after uploading the blob. ```console cxx-demo$ cargo run Compiling cxx-demo v0.1.0 Finished dev [unoptimized + debuginfo] target(s) in 0.41s Running `target/debug/cxx-demo` blobid = 9851996977040795552 ``` -------------------------------- ### Rust CxxString Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/cxxstring.md Demonstrates loading a configuration and accessing a string value from a JSON-like object using CxxString. Requires the `let_cxx_string!` macro for stack allocation. ```rust use cxx::let_cxx_string; #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/json.h"); #[cxx_name = "json"] type Json; #[cxx_name = "object"] type Object; fn isNull(self: &Json) -> bool; fn isNumber(self: &Json) -> bool; fn isString(self: &Json) -> bool; fn isArray(self: &Json) -> bool; fn isObject(self: &Json) -> bool; fn getNumber(self: &Json) -> f64; fn getString(self: &Json) -> &CxxString; fn getArray(self: &Json) -> &CxxVector; fn getObject(self: &Json) -> &Object; #[cxx_name = "at"] fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; fn load_config() -> UniquePtr; } } fn main() { let config = ffi::load_config(); let_cxx_string!(key = "name"); println!("{}", config.getObject().get(&key).getString()); } ``` -------------------------------- ### Generate C++ Headers with cxxbridge-cmd Source: https://context7.com/dtolnay/cxx/llms.txt For non-Cargo builds, use the `cxxbridge` command-line tool to generate C++ header and source files. Install the tool using `cargo install cxxbridge-cmd`. ```bash # Install the command-line tool cargo install cxxbridge-cmd # Generate C++ header file cxxbridge src/main.rs --header > path/to/mybridge.h # Generate C++ source file cxxbridge src/main.rs > path/to/mybridge.cc ``` -------------------------------- ### Rust to C++ String Concatenation Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/string.md Demonstrates how to pass Rust strings to C++ functions for concatenation using CXX. The example includes the Rust main function, the C++ header, and the C++ implementation. ```rust // src/main.rs #[cxx::bridge] mod ffi { struct ConcatRequest { fst: String, snd: String, } unsafe extern "C++" { include!("example/include/concat.h"); fn concat(r: ConcatRequest) -> String; } } fn main() { let concatenated = ffi::concat(ffi::ConcatRequest { fst: "fearless".to_owned(), snd: "concurrency".to_owned(), }); println!("concatenated: {:?}", concatenated); } ``` ```cpp // include/concat.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" rust::String concat(ConcatRequest r); ``` ```cpp // src/concat.cc #include "example/include/concat.h" ust::String concat(ConcatRequest r) { // The full suite of operator overloads hasn't been added // yet on rust::String, but we can get it done like this: return std::string(r.fst) + std::string(r.snd); } ``` -------------------------------- ### Install and Use CXX C++ Code Generator Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Installs the `cxxbridge-cmd` tool and demonstrates its usage to generate C++ code from a Rust source file. The output is directed to stdout. ```console cxx-demo$ cargo install cxxbridge-cmd cxx-demo$ cxxbridge src/main.rs ``` -------------------------------- ### String Conversion and Usage Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/string.md Demonstrates how to use `rust::String` in a C++ function called from Rust, including struct definitions and conversion to `std::string`. ```APIDOC ## String Conversion and Usage Example ### Description This example shows a C++ function `concat` that takes a `ConcatRequest` struct containing two `rust::String` objects and returns a concatenated `rust::String`. It also illustrates how to call this function from Rust. ### Rust Code (`src/main.rs`) ```rust #[cxx::bridge] mod ffi { struct ConcatRequest { fst: String, snd: String, } unsafe extern "C++" { include!("example/include/concat.h"); fn concat(r: ConcatRequest) -> String; } } fn main() { let concatenated = ffi::concat(ffi::ConcatRequest { fst: "fearless".to_owned(), snd: "concurrency".to_owned(), }); println!("concatenated: {:?}", concatenated); } ``` ### C++ Header (`include/concat.h`) ```cpp #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" rust::String concat(ConcatRequest r); ``` ### C++ Implementation (`src/concat.cc`) ```cpp #include "example/include/concat.h" ust::String concat(ConcatRequest r) { // The full suite of operator overloads hasn't been added // yet on rust::String, but we can get it done like this: return std::string(r.fst) + std::string(r.snd); } ``` ``` -------------------------------- ### Rust SharedPtr Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/sharedptr.md Demonstrates creating and managing a shared pointer to a C++ object from Rust. Ensure the `cxx` crate is included in your Cargo.toml. ```rust use std::ops::Deref; use std::ptr; #[cxx::bridge] mod ffi { unsafe extern "C++" { include!("example/include/example.h"); type Object; fn create_shared_ptr() -> SharedPtr; } } fn main() { let ptr1 = ffi::create_shared_ptr(); { // Create a second shared_ptr holding shared ownership of the same // object. There is still only one Object but two SharedPtr. // Both pointers point to the same object on the heap. let ptr2 = ptr1.clone(); assert!(ptr::eq(ptr1.deref(), ptr2.deref())); // ptr2 goes out of scope, but Object is not destroyed yet. } println!("say goodbye to Object"); // ptr1 goes out of scope and Object is destroyed. } ``` -------------------------------- ### Async Pattern Workaround with Oneshot Channels Source: https://context7.com/dtolnay/cxx/llms.txt Use oneshot channels to bridge asynchronous C++ callbacks to Rust futures. This example demonstrates starting an async operation and receiving its result. ```rust use futures::channel::oneshot; #[cxx::bridge] mod ffi { extern "Rust" { type AsyncContext; } unsafe extern "C++" { include!("async/include/async_op.h"); fn start_async_operation( arg: i32, done: fn(Box, result: i32), ctx: Box, ); } } struct AsyncContext(oneshot::Sender); pub async fn async_operation(arg: i32) -> i32 { let (tx, rx) = oneshot::channel(); let context = Box::new(AsyncContext(tx)); ffi::start_async_operation( arg, |context, result| { let _ = context.0.send(result); }, context, ); rx.await.unwrap() } // Usage in async context: // let result = async_operation(42).await; ``` -------------------------------- ### Example Usage: Rust to C++ String Passing Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/str.md Demonstrates how to pass a Rust string slice (`&str`) to a C++ function using `rust::Str` via the cxx bridge. ```APIDOC ## Example Usage: Rust to C++ String Passing ### Description This example illustrates the interaction between Rust and C++ when passing string slices. A Rust function `r` accepts a `&str`, and a C++ function `c` accepts a `rust::Str`. The `cxx::bridge` facilitates this cross-language communication. ### Rust Code (`src/main.rs`) ```rust,noplayground #[cxx::bridge] mod ffi { extern "Rust" { fn r(greeting: &str); } unsafe extern "C++" { include!("example/include/greeting.h"); fn c(greeting: &str); } } fn r(greeting: &str) { println!("{}", greeting); } fn main() { ffi::c("hello from Rust"); } ``` ### C++ Header (`include/greeting.h`) ```cpp #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void c(rust::Str greeting); ``` ### C++ Implementation (`src/greeting.cc`) ```cpp #include "example/include/greeting.h" #include void c(rust::Str greeting) { std::cout << greeting << std::endl; r("hello from C++"); } ``` ``` -------------------------------- ### Rust example using Box for FFI ownership transfer Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/box.md Demonstrates passing ownership of a Rust `File` type (wrapped in `Box`) to C++, which then passes it to a Rust callback. This pattern is useful for implementing async operations over FFI. ```rust // src/main.rs use std::io::Write; #[cxx::bridge] mod ffi { extern "Rust" { type File; } unsafe extern "C++" { include!("example/include/example.h"); fn f( callback: fn(Box, fst: &str, snd: &str), out: Box, ); } } pub struct File(std::fs::File); fn main() { let out = std::fs::File::create("example.log").unwrap(); ffi::f( |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); }, Box::new(File(out)), ); } ``` ```cpp // include/example.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void f(rust::Fn, rust::Str, rust::Str)> callback, rust::Box out); ``` ```cpp // include/example.cc #include "example/include/example.h" void f(rust::Fn, rust::Str, rust::Str)> callback, rust::Box out) { callback(std::move(out), "fearless", "concurrency"); } ``` -------------------------------- ### Opaque Type Definition Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/extern-rust.md An example showing how an opaque type declared in `extern "Rust"` corresponds to a type defined in the parent module, potentially via a `use` statement or direct definition. ```rust use path::to::MyType; pub struct MyOtherType { ... } # # #[cxx::bridge] # mod ffi { # extern "Rust" { # type MyType; # type MyOtherType; # } # } ``` -------------------------------- ### Rust to C++ String Slice Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/str.md Demonstrates passing a Rust string slice (&str) to a C++ function that accepts rust::Str. This involves defining a C++ header and implementation file to handle the interop. ```rust // src/main.rs #[cxx::bridge] mod ffi { extern "Rust" { fn r(greeting: &str); } unsafe extern "C++" { include!("example/include/greeting.h"); fn c(greeting: &str); } } fn r(greeting: &str) { println!("{}", greeting); } fn main() { ffi::c("hello from Rust"); } ``` ```cpp // include/greeting.h #pragma once #include "example/src/main.rs.h" #include "rust/cxx.h" void c(rust::Str greeting); ``` ```cpp // src/greeting.cc #include "example/include/greeting.h" #include void c(rust::Str greeting) { std::cout << greeting << std::endl; r("hello from C++"); } ``` -------------------------------- ### C++ Example: Prettify JSON using Rust Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/slice.md A C++ program that reads JSON from stdin, converts it to a `rust::Slice`, calls the Rust `prettify_json` function, and prints the pretty-printed JSON to stdout. ```cpp // src/main.cc #include "example/src/main.rs.h" #include #include #include #include int main() { // Read json from stdin. std::istreambuf_iterator begin{std::cin}, end; std::vector input{begin, end}; rust::Slice slice{input.data(), input.size()}; // Prettify using serde_json and serde_transcode. std::string output; prettify_json(slice, output); // Write to stdout. std::cout << output << std::endl; } ``` -------------------------------- ### C++ Header for unique_ptr Example Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/uniqueptr.md Declares the C++ function that returns a `std::unique_ptr`. This header is used by both the C++ implementation and the Rust binding. ```cpp // include/blobstore.h #pragma once #include class BlobstoreClient; std::unique_ptr new_blobstore_client(); ``` -------------------------------- ### CXX Bridge Example: Rust and C++ Interop Source: https://github.com/dtolnay/cxx/blob/master/book/src/concepts.md Defines shared structs, opaque types, and functions for Rust and C++ interaction within a CXX bridge. Rust defines `BlobMetadata` and `MultiBuf`, while C++ defines `BlobstoreClient`. This snippet illustrates how to declare types and functions visible to both languages, specifying the source of truth for each. ```rust # #[cxx::bridge] # mod ffi { // Any shared structs, whose fields will be visible to both languages. # struct BlobMetadata { # size: usize, # tags: Vec, # } # # 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 for the // enclosing extern "C++" block. 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; # fn put(&self, parts: &mut MultiBuf) -> u64; # fn tag(&self, blobid: u64, tag: &str); # fn metadata(&self, blobid: u64) -> BlobMetadata; # } # } ``` -------------------------------- ### Rust Main Function Using Blobstore Client Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Demonstrates how to use the C++ `BlobstoreClient` from Rust. It creates a client instance, prepares `MultiBuf` with data chunks, calls the `put` method to upload the blob, and prints the returned blobid. ```rust # # #[cxx::bridge] # mod ffi { # extern "Rust" { # type MultiBuf; # # fn next_chunk(buf: &mut MultiBuf) -> &[u8]; # } # # unsafe extern "C++" { # include!("cxx-demo/include/blobstore.h"); # # type BlobstoreClient; # # fn new_blobstore_client() -> UniquePtr; # fn put(&self, parts: &mut MultiBuf) -> u64; # } # } # # pub struct MultiBuf { # chunks: Vec>, # pos: usize, # } # pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { # let next = buf.chunks.get(buf.pos); # buf.pos += 1; # next.map_or(&[], Vec::as_slice) # } fn main() { let client = ffi::new_blobstore_client(); // Upload a blob. let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); println!("blobid = {blobid}"); } ``` -------------------------------- ### C++ Blobstore Client Implementation Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Provides the implementation for the BlobstoreClient class and the `new_blobstore_client` function. Ensure C++14 compatibility if using `std::make_unique`. ```cpp #include "cxx-demo/include/blobstore.h" BlobstoreClient::BlobstoreClient() {} std::unique_ptr new_blobstore_client() { return std::unique_ptr(new BlobstoreClient()); } ``` -------------------------------- ### C++ BlobstoreClient Implementation Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md This C++ source file provides the implementation for the BlobstoreClient class, including methods for putting blobs, tagging them, and retrieving metadata. It uses an in-memory map for storage. ```cpp // src/blobstore.cc #include "cxx-demo/include/blobstore.h" #include "cxx-demo/src/main.rs.h" #include #include #include #include #include // Toy implementation of an in-memory blobstore. // // In reality the implementation of BlobstoreClient could be a large // complex C++ library. class BlobstoreClient::impl { friend BlobstoreClient; using Blob = struct { std::string data; std::set tags; }; std::unordered_map blobs; }; BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} // Upload a new blob and return a blobid that serves as a handle to the blob. uint64_t BlobstoreClient::put(MultiBuf &buf) const { // Traverse the caller's chunk iterator. std::string contents; while (true) { auto chunk = next_chunk(buf); if (chunk.size() == 0) { break; } contents.append(reinterpret_cast(chunk.data()), chunk.size()); } // Insert into map and provide caller the handle. auto blobid = std::hash{}(contents); impl->blobs[blobid] = {std::move(contents), {}}; return blobid; } // Add tag to an existing blob. void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { impl->blobs[blobid].tags.emplace(tag); } // Retrieve metadata about a blob. BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { BlobMetadata metadata{}; auto blob = impl->blobs.find(blobid); if (blob != impl->blobs.end()) { metadata.size = blob->second.data.size(); std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(), [&](auto &t) { metadata.tags.emplace_back(t); }); } return metadata; } std::unique_ptr new_blobstore_client() { return std::make_unique(); } ``` -------------------------------- ### C++ Implementation of Blobstore Client Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Provides the C++ implementation for the `BlobstoreClient` constructor and the `new_blobstore_client` function. The `put` method demonstrates calling the Rust `next_chunk` function to retrieve data chunks and then processes them. ```cpp // src/blobstore.cc #include "cxx-demo/include/blobstore.h" #include "cxx-demo/src/main.rs.h" #include #include ... ...BlobstoreClient::BlobstoreClient() {} ... ...std::unique_ptr new_blobstore_client() { ... return std::make_unique(); ... } // Upload a new blob and return a blobid that serves as a handle to the blob. uint64_t BlobstoreClient::put(MultiBuf &buf) const { // Traverse the caller's chunk iterator. std::string contents; while (true) { auto chunk = next_chunk(buf); if (chunk.size() == 0) { break; } contents.append(reinterpret_cast(chunk.data()), chunk.size()); } // Pretend we did something useful to persist the data. auto blobid = std::hash{}(contents); return blobid; } ``` -------------------------------- ### Async Function Implementation in C++ Source: https://github.com/dtolnay/cxx/blob/master/book/src/async.md Implement an asynchronous function in C++ that can be called from Rust via CXX. This example uses C++20 coroutines. ```cpp rust::Future doThing(Arg arg) { auto v1 = co_await f(); auto v2 = co_await g(arg); co_return v1 + v2; } ``` -------------------------------- ### C++ Implementation for Async Operation Source: https://context7.com/dtolnay/cxx/llms.txt This C++ code provides the implementation for `start_async_operation`, simulating asynchronous work and then invoking the provided callback with the result. ```cpp // async/include/async_op.h #include "path/to/bridge.rs.h" #include "rust/cxx.h" void start_async_operation( int32_t arg, rust::Fn, int32_t)> done, rust::Box ctx); // async/src/async_op.cc void start_async_operation( int32_t arg, rust::Fn, int32_t)> done, rust::Box ctx) { // Simulate async work, then call the callback auto result = arg * 2; (*done)(std::move(ctx), result); } ``` -------------------------------- ### C++ JSON Implementation and Config Loading Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/cxxstring.md Provides the implementation for the JSON class methods and a function to load a sample configuration object. The configuration includes a map with string keys and various JSON types. ```cpp #include "example/include/json.h" #include #include const json json::null{}; bool json::isNull() const { return std::holds_alternative(value); } bool json::isNumber() const { return std::holds_alternative(value); } bool json::isString() const { return std::holds_alternative(value); } bool json::isArray() const { return std::holds_alternative(value); } bool json::isObject() const { return std::holds_alternative(value); } json::number json::getNumber() const { return std::get(value); } const json::string &json::getString() const { return std::get(value); } const json::array &json::getArray() const { return std::get(value); } const json::object &json::getObject() const { return std::get(value); } std::unique_ptr load_config() { return std::make_unique( std::in_place_type, std::initializer_list>{ {"name", "cxx-example"}, {"edition", 2021.}, {"repository", json::null}}); } ``` -------------------------------- ### Pattern Matching with Shared Enums in Rust Source: https://github.com/dtolnay/cxx/blob/master/book/src/shared.md Example of pattern matching on a shared enum in Rust. Wildcard arms are necessary to handle potential values not explicitly listed as variants. ```rust fn main() { let suit: Suit = /*வுகளை*/; match suit { Suit::Clubs => ..., Suit::Diamonds => ..., Suit::Hearts => ..., Suit::Spades => ..., _ => ..., // fallback arm } } ``` -------------------------------- ### Reusing Binding Types Across Modules Source: https://context7.com/dtolnay/cxx/llms.txt Share type definitions across multiple bridge modules using type aliases and the `ExternType` trait. This example shows how `file2.rs` reuses `SharedResource` defined in `file1.rs`. ```rust // file1.rs - defines the canonical type #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { include!("example/include/types.h"); type SharedResource; fn create_resource() -> UniquePtr; } } // file2.rs - reuses the type from file1 #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { include!("example/include/processor.h"); // Alias to the type defined in file1 type SharedResource = crate::file1::ffi::SharedResource; fn process_resource(res: &SharedResource) -> i32; } } // Now both modules use the same Rust type fn main() { let resource = crate::file1::ffi::create_resource(); let result = crate::file2::ffi::process_resource(&resource); println!("Result: {}", result); } ``` -------------------------------- ### Cargo.toml configuration for CXX Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/cargo.md Add cxx and cxx-build as dependencies in your Cargo.toml file to enable C++ integration. ```toml # Cargo.toml ...[package] ...name = "..." ...version = "..." ...edition = "2021" [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` -------------------------------- ### Export Header Directories for System Libraries Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/cargo.md Use `CFG.exported_header_dirs` to make system library headers, like Python.h, available to downstream crates. Ensure your crate has a `links` key in Cargo.toml. ```rust // build.rs use cxx_build::CFG; use std::path::PathBuf; fn main() { let python3 = pkg_config::probe_library("python3").unwrap(); let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path); CFG.exported_header_dirs.extend(python_include_paths); cxx_build::bridge("src/bridge.rs").compile("demo"); } ``` -------------------------------- ### C++ Blobstore Header Definition Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Defines the BlobstoreClient class and a function to create a client instance. This header is included by C++ source files and Rust bindings. ```cpp #pragma once #include class BlobstoreClient { public: BlobstoreClient(); }; std::unique_ptr new_blobstore_client(); ``` -------------------------------- ### C++ Main Function to Call Rust Bridge Source: https://github.com/dtolnay/cxx/blob/master/book/src/binding/cxxvector.md This C++ code initializes a std::vector and passes it to the Rust function 'f' via the C++ header generated by cxx. This demonstrates the inter-language communication setup. ```cpp #include "example/src/main.rs.h" #include #include int main() { std::vector vec{"fearless", "concurrency"}; f(vec); } ``` -------------------------------- ### Build Script for Cargo Projects Source: https://github.com/dtolnay/cxx/blob/master/README.md Use this `build.rs` script to integrate CXX into your Cargo project. It generates C++ code and compiles it with your crate. ```rust // build.rs fn main() { cxx_build::bridge("src/main.rs") // returns a cc::Build .file("src/demo.cc") .std("c++11") .compile("cxxbridge-demo"); println!("cargo:rerun-if-changed=src/demo.cc"); println!("cargo:rerun-if-changed=include/demo.h"); } ``` -------------------------------- ### Unify Extern Type Occurrences Across Bridges Source: https://github.com/dtolnay/cxx/blob/master/book/src/extern-c++.md In separate bridge modules, declare `type Demo;` for C++ `example::Demo`. To unify them, one module should alias the other using `type Demo = crate::file1::ffi::Demo;` to ensure they represent the same Rust type. ```rust // file1.rs #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { type Demo; fn create_demo() -> UniquePtr; } } ``` ```rust // file2.rs #[cxx::bridge(namespace = "example")] pub mod ffi { unsafe extern "C++" { type Demo = crate::file1::ffi::Demo; fn take_ref_demo(demo: &Demo); } } ``` -------------------------------- ### Rust Blobstore Client Usage Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md This Rust code demonstrates how to use the C++ BlobstoreClient to upload a blob, add a tag, and retrieve metadata. Ensure the C++ BlobstoreClient is correctly linked. ```rust fn main() { let client = ffi::new_blobstore_client(); // Upload a blob. let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); println!("blobid = {blobid}"); // Add a tag. client.tag(blobid, "rust"); // Read back the tags. let metadata = client.metadata(blobid); println!("tags = {:?}", metadata.tags); } ``` -------------------------------- ### Define Rust and C++ Bridge Interface Source: https://github.com/dtolnay/cxx/blob/master/book/src/index.md Use the `#[cxx::bridge]` macro to define the interface between Rust and C++. This example shows how to declare types and functions that will be shared across the boundary. Ensure that all types and functions declared in `extern "Rust"` have corresponding Rust definitions and those in `extern "C++"` have corresponding C++ definitions. ```rust #[cxx::bridge] mod ffi { extern "Rust" { type MultiBuf; fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } unsafe extern "C++" { include!("example/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result; } } ``` -------------------------------- ### Add CXX Dependency to Cargo.toml Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Add the `cxx` crate as a dependency in your `Cargo.toml` file to enable C++ interop. ```toml # Cargo.toml ...[package] ...name = "cxx-demo" ...version = "0.1.0" ...edition = "2021" [dependencies] cxx = "1.0" ``` -------------------------------- ### Define FFI Boundary with #[cxx::bridge] Source: https://context7.com/dtolnay/cxx/llms.txt The `#[cxx::bridge]` macro defines the FFI boundary. Use `extern "Rust"` for Rust items exposed to C++ and `extern "C++"` for C++ items exposed to Rust. This example demonstrates shared structs, Rust types exposed to C++, and C++ types exposed to Rust. ```rust #[cxx::bridge] mod ffi { // Shared structs visible to both languages struct BlobMetadata { size: usize, tags: Vec, } // Rust types and functions exposed to C++ extern "Rust" { type MultiBuf; fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } // C++ types and functions exposed to Rust unsafe extern "C++" { include!("demo/include/blobstore.h"); type BlobstoreClient; fn new_blobstore_client() -> UniquePtr; fn put(&self, parts: &mut MultiBuf) -> u64; fn tag(&self, blobid: u64, tag: &str); fn metadata(&self, blobid: u64) -> BlobMetadata; } } // Implement the Rust types declared in extern "Rust" pub struct MultiBuf { chunks: Vec>, pos: usize, } pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { let next = buf.chunks.get(buf.pos); buf.pos += 1; next.map_or(&[], Vec::as_slice) } fn main() { let client = ffi::new_blobstore_client(); // Upload a blob let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; let mut buf = MultiBuf { chunks, pos: 0 }; let blobid = client.put(&mut buf); println!("blobid = {blobid}"); // Add a tag and read metadata client.tag(blobid, "rust"); let metadata = client.metadata(blobid); println!("tags = {:?}", metadata.tags); } ``` -------------------------------- ### Command to Expand CXX Bridge Macros Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Instructions on how to use `cargo-expand` to inspect the Rust code generated by the CXX bridge, useful for understanding the underlying mechanisms. ```console cxx-demo$ cargo install cargo-expand cxx-demo$ cargo expand ::ffi ``` -------------------------------- ### Cargo.toml for CXX Build Dependencies Source: https://github.com/dtolnay/cxx/blob/master/README.md Add `cxx-build` to your build dependencies in Cargo.toml to enable CXX's C++ code generation. ```toml # Cargo.toml [build-dependencies] cxx-build = "1.0" ``` -------------------------------- ### Cargo.toml Configuration for CXX Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Adds `cxx` as a regular dependency and `cxx-build` as a build dependency in Cargo.toml. This enables CXX's code generation and C++ compilation. ```toml # Cargo.toml ... [package] ...name = "cxx-demo" ...version = "0.1.0" ...edition = "2021" [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` -------------------------------- ### Including headers from dependencies in C++ Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/cargo.md Include headers from direct dependencies by prefixing with the dependency's crate name (or its include_prefix) followed by the header's relative path. ```cpp #include "dependencycratename/path/to/their/header.h" ``` -------------------------------- ### Cargo Build Configuration for CXX Source: https://context7.com/dtolnay/cxx/llms.txt Configure your `Cargo.toml` and `build.rs` to use `cxx-build` for compiling C++ code and generating the bridge. The `bridge()` function returns a `cc::Build` instance for further configuration. ```toml # Cargo.toml [dependencies] cxx = "1.0" [build-dependencies] cxx-build = "1.0" ``` ```rust // build.rs fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") .std("c++14") .compile("cxxbridge-demo"); println!("cargo:rerun-if-changed=src/blobstore.cc"); println!("cargo:rerun-if-changed=include/blobstore.h"); } ``` -------------------------------- ### C++ BlobstoreClient Header Definition Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md This C++ header defines the BlobstoreClient class and related structures, intended to be used from Rust via CXX. It declares methods for blob manipulation and metadata retrieval. ```cpp // include/blobstore.h #pragma once #include "rust/cxx.h" #include struct MultiBuf; struct BlobMetadata; class BlobstoreClient { public: BlobstoreClient(); uint64_t put(MultiBuf &buf) const; void tag(uint64_t blobid, rust::Str tag) const; BlobMetadata metadata(uint64_t blobid) const; private: class impl; std::shared_ptr impl; }; std::unique_ptr new_blobstore_client(); ``` -------------------------------- ### C++ Header for Blobstore Client Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Declares the C++ `BlobstoreClient` class and the `new_blobstore_client` function, along with the `MultiBuf` struct, which will be used by C++ code interacting with Rust. ```cpp // include/blobstore.h ...#pragma once ...#include ... struct MultiBuf; class BlobstoreClient { public: BlobstoreClient(); uint64_t put(MultiBuf &buf) const; }; ... ...std::unique_ptr new_blobstore_client(); ``` -------------------------------- ### Generate C++ Bindings with cxxbridge-cmd Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/bazel.md Use the `cxxbridge-cmd` tool to generate C++ header and source files from a Rust bridge file. The `--header` flag generates the header file, while omitting it generates the C++ source file. ```bash $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h ``` ```bash $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc ``` -------------------------------- ### Generate C++ Bindings with cxxbridge CLI Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/other.md Use the `cxxbridge` command-line tool to generate C++ header and source files from your Rust bridge definitions. Ensure the `cxxbridge-cmd` version matches the `cxx` crate version. ```console $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc ``` -------------------------------- ### Namespace Control with `cxx::bridge` Source: https://github.com/dtolnay/cxx/blob/master/book/src/attributes.md Demonstrates how to control the C++ namespace for emitted Rust items and expected C++ items using the `namespace` argument in the `cxx::bridge` attribute macro. ```APIDOC ## `cxx::bridge` Namespace Control ### Description Controls the C++ namespace for emitted Rust items and expected C++ items. ### Method Attribute Macro ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```rust #[cxx::bridge(namespace = "path::of::my::company")] mod ffi { extern "Rust" { type MyType; // emitted to path::of::my::company::MyType } extern "C++" { type TheirType; // refers to path::of::my::company::TheirType } } ``` ### Response N/A ## Nested Namespace Attributes ### Description Allows specifying namespaces on inner extern blocks or individual items, which inherit from outer scopes or the top-level `cxx::bridge` attribute. ### Method Attribute Macro ### Endpoint N/A ### Parameters N/A #### Request Body N/A ### Request Example ```rust #[cxx::bridge(namespace = "third_priority")] mod ffi { #[namespace = "second_priority"] extern "Rust" { fn f(); #[namespace = "first_priority"] fn g(); } extern "Rust" { fn h(); } } ``` ### Response N/A **Resulting functions:** `::second_priority::f`, `::first_priority::g`, `::third_priority::h`. ``` -------------------------------- ### Build Script for CXX Compilation Source: https://github.com/dtolnay/cxx/blob/master/book/src/tutorial.md Configures the build process using `cxx-build::bridge`. It specifies the main Rust file with the bridge definition and additional C++ source files to compile. ```rust // build.rs fn main() { cxx_build::bridge("src/main.rs") .file("src/blobstore.cc") .compile("cxx-demo"); println!("cargo:rerun-if-changed=src/blobstore.cc"); println!("cargo:rerun-if-changed=include/blobstore.h"); } ``` -------------------------------- ### Including CXX-generated headers in C++ Source: https://github.com/dtolnay/cxx/blob/master/book/src/build/cargo.md Include CXX-generated headers in your C++ code using the '.rs.h' extension or a plain '.rs' extension, prefixed by the crate name. ```cpp // the header generated from path/to/lib.rs #include "yourcratename/path/to/lib.rs.h" ``` ```cpp #include "yourcratename/path/to/lib.rs" ```