133d722a9Sopenharmony_ci{{#title std::string — Rust ♡ C++}} 233d722a9Sopenharmony_ci# std::string 333d722a9Sopenharmony_ci 433d722a9Sopenharmony_ciThe Rust binding of std::string is called **[`CxxString`]**. See the link for 533d722a9Sopenharmony_cidocumentation of the Rust API. 633d722a9Sopenharmony_ci 733d722a9Sopenharmony_ci[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html 833d722a9Sopenharmony_ci 933d722a9Sopenharmony_ci### Restrictions: 1033d722a9Sopenharmony_ci 1133d722a9Sopenharmony_ciRust code can never obtain a CxxString by value. C++'s string requires a move 1233d722a9Sopenharmony_ciconstructor and may hold internal pointers, which is not compatible with Rust's 1333d722a9Sopenharmony_cimove behavior. Instead in Rust code we will only ever look at a CxxString 1433d722a9Sopenharmony_cithrough a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\> 1533d722a9Sopenharmony_cior UniquePtr\<CxxString\>. 1633d722a9Sopenharmony_ci 1733d722a9Sopenharmony_ciIn order to construct a CxxString on the stack from Rust, you must use the 1833d722a9Sopenharmony_ci[`let_cxx_string!`] macro which will pin the string properly. The code below 1933d722a9Sopenharmony_ciuses this in one place, and the link covers the syntax. 2033d722a9Sopenharmony_ci 2133d722a9Sopenharmony_ci[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html 2233d722a9Sopenharmony_ci 2333d722a9Sopenharmony_ci## Example 2433d722a9Sopenharmony_ci 2533d722a9Sopenharmony_ciThis example uses C++17's std::variant to build a toy JSON type. JSON can hold 2633d722a9Sopenharmony_civarious types including strings, and JSON's object type is a map with string 2733d722a9Sopenharmony_cikeys. The example demonstrates Rust indexing into one of those maps. 2833d722a9Sopenharmony_ci 2933d722a9Sopenharmony_ci```rust,noplayground 3033d722a9Sopenharmony_ci// src/main.rs 3133d722a9Sopenharmony_ci 3233d722a9Sopenharmony_ciuse cxx::let_cxx_string; 3333d722a9Sopenharmony_ci 3433d722a9Sopenharmony_ci#[cxx::bridge] 3533d722a9Sopenharmony_cimod ffi { 3633d722a9Sopenharmony_ci unsafe extern "C++" { 3733d722a9Sopenharmony_ci include!("example/include/json.h"); 3833d722a9Sopenharmony_ci 3933d722a9Sopenharmony_ci #[cxx_name = "json"] 4033d722a9Sopenharmony_ci type Json; 4133d722a9Sopenharmony_ci #[cxx_name = "object"] 4233d722a9Sopenharmony_ci type Object; 4333d722a9Sopenharmony_ci 4433d722a9Sopenharmony_ci fn isNull(self: &Json) -> bool; 4533d722a9Sopenharmony_ci fn isNumber(self: &Json) -> bool; 4633d722a9Sopenharmony_ci fn isString(self: &Json) -> bool; 4733d722a9Sopenharmony_ci fn isArray(self: &Json) -> bool; 4833d722a9Sopenharmony_ci fn isObject(self: &Json) -> bool; 4933d722a9Sopenharmony_ci 5033d722a9Sopenharmony_ci fn getNumber(self: &Json) -> f64; 5133d722a9Sopenharmony_ci fn getString(self: &Json) -> &CxxString; 5233d722a9Sopenharmony_ci fn getArray(self: &Json) -> &CxxVector<Json>; 5333d722a9Sopenharmony_ci fn getObject(self: &Json) -> &Object; 5433d722a9Sopenharmony_ci 5533d722a9Sopenharmony_ci #[cxx_name = "at"] 5633d722a9Sopenharmony_ci fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; 5733d722a9Sopenharmony_ci 5833d722a9Sopenharmony_ci fn load_config() -> UniquePtr<Json>; 5933d722a9Sopenharmony_ci } 6033d722a9Sopenharmony_ci} 6133d722a9Sopenharmony_ci 6233d722a9Sopenharmony_cifn main() { 6333d722a9Sopenharmony_ci let config = ffi::load_config(); 6433d722a9Sopenharmony_ci 6533d722a9Sopenharmony_ci let_cxx_string!(key = "name"); 6633d722a9Sopenharmony_ci println!("{}", config.getObject().get(&key).getString()); 6733d722a9Sopenharmony_ci} 6833d722a9Sopenharmony_ci``` 6933d722a9Sopenharmony_ci 7033d722a9Sopenharmony_ci```cpp 7133d722a9Sopenharmony_ci// include/json.h 7233d722a9Sopenharmony_ci 7333d722a9Sopenharmony_ci#pragma once 7433d722a9Sopenharmony_ci#include <map> 7533d722a9Sopenharmony_ci#include <memory> 7633d722a9Sopenharmony_ci#include <string> 7733d722a9Sopenharmony_ci#include <variant> 7833d722a9Sopenharmony_ci#include <vector> 7933d722a9Sopenharmony_ci 8033d722a9Sopenharmony_ciclass json final { 8133d722a9Sopenharmony_cipublic: 8233d722a9Sopenharmony_ci static const json null; 8333d722a9Sopenharmony_ci using number = double; 8433d722a9Sopenharmony_ci using string = std::string; 8533d722a9Sopenharmony_ci using array = std::vector<json>; 8633d722a9Sopenharmony_ci using object = std::map<string, json>; 8733d722a9Sopenharmony_ci 8833d722a9Sopenharmony_ci json() noexcept = default; 8933d722a9Sopenharmony_ci json(const json &) = default; 9033d722a9Sopenharmony_ci json(json &&) = default; 9133d722a9Sopenharmony_ci template <typename... T> 9233d722a9Sopenharmony_ci json(T &&...value) : value(std::forward<T>(value)...) {} 9333d722a9Sopenharmony_ci 9433d722a9Sopenharmony_ci bool isNull() const; 9533d722a9Sopenharmony_ci bool isNumber() const; 9633d722a9Sopenharmony_ci bool isString() const; 9733d722a9Sopenharmony_ci bool isArray() const; 9833d722a9Sopenharmony_ci bool isObject() const; 9933d722a9Sopenharmony_ci 10033d722a9Sopenharmony_ci number getNumber() const; 10133d722a9Sopenharmony_ci const string &getString() const; 10233d722a9Sopenharmony_ci const array &getArray() const; 10333d722a9Sopenharmony_ci const object &getObject() const; 10433d722a9Sopenharmony_ci 10533d722a9Sopenharmony_ciprivate: 10633d722a9Sopenharmony_ci std::variant<std::monostate, number, string, array, object> value; 10733d722a9Sopenharmony_ci}; 10833d722a9Sopenharmony_ci 10933d722a9Sopenharmony_ciusing object = json::object; 11033d722a9Sopenharmony_ci 11133d722a9Sopenharmony_cistd::unique_ptr<json> load_config(); 11233d722a9Sopenharmony_ci``` 11333d722a9Sopenharmony_ci 11433d722a9Sopenharmony_ci```cpp 11533d722a9Sopenharmony_ci// include/json.cc 11633d722a9Sopenharmony_ci 11733d722a9Sopenharmony_ci#include "example/include/json.h" 11833d722a9Sopenharmony_ci#include <initializer_list> 11933d722a9Sopenharmony_ci#include <utility> 12033d722a9Sopenharmony_ci 12133d722a9Sopenharmony_ciconst json json::null{}; 12233d722a9Sopenharmony_cibool json::isNull() const { return std::holds_alternative<std::monostate>(value); } 12333d722a9Sopenharmony_cibool json::isNumber() const { return std::holds_alternative<number>(value); } 12433d722a9Sopenharmony_cibool json::isString() const { return std::holds_alternative<string>(value); } 12533d722a9Sopenharmony_cibool json::isArray() const { return std::holds_alternative<array>(value); } 12633d722a9Sopenharmony_cibool json::isObject() const { return std::holds_alternative<object>(value); } 12733d722a9Sopenharmony_cijson::number json::getNumber() const { return std::get<number>(value); } 12833d722a9Sopenharmony_ciconst json::string &json::getString() const { return std::get<string>(value); } 12933d722a9Sopenharmony_ciconst json::array &json::getArray() const { return std::get<array>(value); } 13033d722a9Sopenharmony_ciconst json::object &json::getObject() const { return std::get<object>(value); } 13133d722a9Sopenharmony_ci 13233d722a9Sopenharmony_cistd::unique_ptr<json> load_config() { 13333d722a9Sopenharmony_ci return std::make_unique<json>( 13433d722a9Sopenharmony_ci std::in_place_type<json::object>, 13533d722a9Sopenharmony_ci std::initializer_list<std::pair<const std::string, json>>{ 13633d722a9Sopenharmony_ci {"name", "cxx-example"}, 13733d722a9Sopenharmony_ci {"edition", 2018.}, 13833d722a9Sopenharmony_ci {"repository", json::null}}); 13933d722a9Sopenharmony_ci} 14033d722a9Sopenharmony_ci``` 141