1{{#title std::string — Rust ♡ C++}} 2# std::string 3 4The Rust binding of std::string is called **[`CxxString`]**. See the link for 5documentation of the Rust API. 6 7[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html 8 9### Restrictions: 10 11Rust code can never obtain a CxxString by value. C++'s string requires a move 12constructor and may hold internal pointers, which is not compatible with Rust's 13move behavior. Instead in Rust code we will only ever look at a CxxString 14through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\> 15or UniquePtr\<CxxString\>. 16 17In order to construct a CxxString on the stack from Rust, you must use the 18[`let_cxx_string!`] macro which will pin the string properly. The code below 19uses this in one place, and the link covers the syntax. 20 21[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html 22 23## Example 24 25This example uses C++17's std::variant to build a toy JSON type. JSON can hold 26various types including strings, and JSON's object type is a map with string 27keys. The example demonstrates Rust indexing into one of those maps. 28 29```rust,noplayground 30// src/main.rs 31 32use cxx::let_cxx_string; 33 34#[cxx::bridge] 35mod ffi { 36 unsafe extern "C++" { 37 include!("example/include/json.h"); 38 39 #[cxx_name = "json"] 40 type Json; 41 #[cxx_name = "object"] 42 type Object; 43 44 fn isNull(self: &Json) -> bool; 45 fn isNumber(self: &Json) -> bool; 46 fn isString(self: &Json) -> bool; 47 fn isArray(self: &Json) -> bool; 48 fn isObject(self: &Json) -> bool; 49 50 fn getNumber(self: &Json) -> f64; 51 fn getString(self: &Json) -> &CxxString; 52 fn getArray(self: &Json) -> &CxxVector<Json>; 53 fn getObject(self: &Json) -> &Object; 54 55 #[cxx_name = "at"] 56 fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; 57 58 fn load_config() -> UniquePtr<Json>; 59 } 60} 61 62fn main() { 63 let config = ffi::load_config(); 64 65 let_cxx_string!(key = "name"); 66 println!("{}", config.getObject().get(&key).getString()); 67} 68``` 69 70```cpp 71// include/json.h 72 73#pragma once 74#include <map> 75#include <memory> 76#include <string> 77#include <variant> 78#include <vector> 79 80class json final { 81public: 82 static const json null; 83 using number = double; 84 using string = std::string; 85 using array = std::vector<json>; 86 using object = std::map<string, json>; 87 88 json() noexcept = default; 89 json(const json &) = default; 90 json(json &&) = default; 91 template <typename... T> 92 json(T &&...value) : value(std::forward<T>(value)...) {} 93 94 bool isNull() const; 95 bool isNumber() const; 96 bool isString() const; 97 bool isArray() const; 98 bool isObject() const; 99 100 number getNumber() const; 101 const string &getString() const; 102 const array &getArray() const; 103 const object &getObject() const; 104 105private: 106 std::variant<std::monostate, number, string, array, object> value; 107}; 108 109using object = json::object; 110 111std::unique_ptr<json> load_config(); 112``` 113 114```cpp 115// include/json.cc 116 117#include "example/include/json.h" 118#include <initializer_list> 119#include <utility> 120 121const json json::null{}; 122bool json::isNull() const { return std::holds_alternative<std::monostate>(value); } 123bool json::isNumber() const { return std::holds_alternative<number>(value); } 124bool json::isString() const { return std::holds_alternative<string>(value); } 125bool json::isArray() const { return std::holds_alternative<array>(value); } 126bool json::isObject() const { return std::holds_alternative<object>(value); } 127json::number json::getNumber() const { return std::get<number>(value); } 128const json::string &json::getString() const { return std::get<string>(value); } 129const json::array &json::getArray() const { return std::get<array>(value); } 130const json::object &json::getObject() const { return std::get<object>(value); } 131 132std::unique_ptr<json> load_config() { 133 return std::make_unique<json>( 134 std::in_place_type<json::object>, 135 std::initializer_list<std::pair<const std::string, json>>{ 136 {"name", "cxx-example"}, 137 {"edition", 2018.}, 138 {"repository", json::null}}); 139} 140``` 141