• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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