1e41f4b71Sopenharmony_ci# Interactive Tool User Guide
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Introduction
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciYou can use Bindgen and CXX to implement the interaction between Rust and C/C++. Bindgen enables Rust to call C by converting C interfaces into Rust interfaces. CXX implement interaction between C++ and Rust by generating bindings between C interfaces and Rust interfaces.
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci![bindgen_and_cxx_tools](./figures/bindgen_and_cxx_tools.png)
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci## Using Bindgen
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci### Procedure
12e41f4b71Sopenharmony_ciThe following example shows how to use Bindgen to implement invocation of C by Rust.
13e41f4b71Sopenharmony_ci
14e41f4b71Sopenharmony_ci1. In the header file **lib.h**, define two interfaces **FuncAAddB** and **SayHello** in C. The **FuncAAddB** interface calculates the sum of two numbers, and the **SayHello** interface prints strings.
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci   ```c
17e41f4b71Sopenharmony_ci   #ifndef BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
18e41f4b71Sopenharmony_ci   #define BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
19e41f4b71Sopenharmony_ci   #include <stdint.h>
20e41f4b71Sopenharmony_ci   #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib2.h"
21e41f4b71Sopenharmony_ci   
22e41f4b71Sopenharmony_ci   uint32_t FuncAAddB(uint32_t a, uint32_t b);
23e41f4b71Sopenharmony_ci   void SayHello(const char *message);
24e41f4b71Sopenharmony_ci   
25e41f4b71Sopenharmony_ci   #endif  //  BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
26e41f4b71Sopenharmony_ci   ```
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci2. Add the implementation of the two interfaces to **lib.c**.
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ci   ```c
32e41f4b71Sopenharmony_ci   #include "build/rust/tests/test_bindgen_test/test_for_hello_world/lib.h"
33e41f4b71Sopenharmony_ci   #include <stdint.h>
34e41f4b71Sopenharmony_ci   #include <stdio.h>
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci   void SayHello(const char *message)
37e41f4b71Sopenharmony_ci   {
38e41f4b71Sopenharmony_ci       printf("This is a test for bindgen hello world:\n");
39e41f4b71Sopenharmony_ci       printf("%s\n", message);
40e41f4b71Sopenharmony_ci   }
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci   uint32_t FuncAAddB(uint32_t a, uint32_t b)
43e41f4b71Sopenharmony_ci   {
44e41f4b71Sopenharmony_ci       printf("This is a test for bindgen of a + b:\n");
45e41f4b71Sopenharmony_ci       return a + b;
46e41f4b71Sopenharmony_ci   }
47e41f4b71Sopenharmony_ci   ```
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci3. Create the **main.rs** file to call C interfaces through c_ffi using Rust. Note that insecure interfaces called by Rust must be encapsulated by using **unsafe**.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci   ```rust
52e41f4b71Sopenharmony_ci   //!  bindgen test for hello world
53e41f4b71Sopenharmony_ci   #![allow(clippy::approx_constant)]
54e41f4b71Sopenharmony_ci   mod c_ffi {
55e41f4b71Sopenharmony_ci       #![allow(dead_code)]
56e41f4b71Sopenharmony_ci       #![allow(non_upper_case_globals)]
57e41f4b71Sopenharmony_ci       #![allow(non_camel_case_types)]
58e41f4b71Sopenharmony_ci       include!(env!("BINDGEN_RS_FILE"));
59e41f4b71Sopenharmony_ci   }
60e41f4b71Sopenharmony_ci   /// pub fn add_two_numbers_in_c
61e41f4b71Sopenharmony_ci   pub fn add_two_numbers_in_c(a: u32, b: u32) -> u32 {
62e41f4b71Sopenharmony_ci       unsafe { c_ffi::FuncAAddB(a, b) }
63e41f4b71Sopenharmony_ci   }
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ci   use std::ffi::c_char;
66e41f4b71Sopenharmony_ci   use std::ffi::CString;
67e41f4b71Sopenharmony_ci
68e41f4b71Sopenharmony_ci   /// fn main()
69e41f4b71Sopenharmony_ci   fn main() {
70e41f4b71Sopenharmony_ci       println!("{} + {} = {}", 3, 7, add_two_numbers_in_c(3, 7));
71e41f4b71Sopenharmony_ci       let c_str = CString::new("This is a message from C").unwrap();
72e41f4b71Sopenharmony_ci       let c_world: *const c_char = c_str.as_ptr() as *const c_char;
73e41f4b71Sopenharmony_ci       unsafe {
74e41f4b71Sopenharmony_ci           c_ffi::SayHello(c_world);
75e41f4b71Sopenharmony_ci       }
76e41f4b71Sopenharmony_ci   }
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci   ```
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci4. Create the **BUILD.gn** file to define the dependency of the Rust module on the C module.
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci   ```GN
83e41f4b71Sopenharmony_ci   import("//build/ohos.gni")
84e41f4b71Sopenharmony_ci
85e41f4b71Sopenharmony_ci   ohos_shared_library("c_lib") {
86e41f4b71Sopenharmony_ci     sources = [ "lib.c" ]
87e41f4b71Sopenharmony_ci     defines = [ "COMPONENT_IMPLEMENTATION" ]
88e41f4b71Sopenharmony_ci   }
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ci   rust_bindgen("c_lib_bindgen") {
91e41f4b71Sopenharmony_ci     header = "lib.h"
92e41f4b71Sopenharmony_ci   }
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci   ohos_rust_executable("bindgen_test") {
95e41f4b71Sopenharmony_ci     deps = [ ":c_lib" ]
96e41f4b71Sopenharmony_ci     deps += [ ":c_lib_bindgen" ]
97e41f4b71Sopenharmony_ci     sources = [ "main.rs" ]
98e41f4b71Sopenharmony_ci     bindgen_output = get_target_outputs(":c_lib_bindgen")
99e41f4b71Sopenharmony_ci     inputs = bindgen_output
100e41f4b71Sopenharmony_ci     rustenv = [ "BINDGEN_RS_FILE=" + rebase_path(bindgen_output[0]) ]
101e41f4b71Sopenharmony_ci     crate_root = "main.rs"
102e41f4b71Sopenharmony_ci   }
103e41f4b71Sopenharmony_ci   ```
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci**Verification**
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci![bindgen_test](./figures/bindgen_test.png)
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci## Using CXX
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci### Calling Rust Interfaces by C++
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ci1. In the Rust **lib.rs** file, add the C++ interfaces to be called in **mod ffi**, and add the interfaces in **extern "Rust"** to expose them to C++. 
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ci   ```rust
117e41f4b71Sopenharmony_ci   //! #[cxx::bridge]
118e41f4b71Sopenharmony_ci   #[cxx::bridge]
119e41f4b71Sopenharmony_ci   mod ffi{
120e41f4b71Sopenharmony_ci       #![allow(dead_code)]
121e41f4b71Sopenharmony_ci       #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
122e41f4b71Sopenharmony_ci       struct Shared {
123e41f4b71Sopenharmony_ci           z: usize,
124e41f4b71Sopenharmony_ci       }
125e41f4b71Sopenharmony_ci       extern "Rust"{
126e41f4b71Sopenharmony_ci           fn print_message_in_rust();
127e41f4b71Sopenharmony_ci           fn r_return_primitive() -> usize;
128e41f4b71Sopenharmony_ci           fn r_return_shared() -> Shared;
129e41f4b71Sopenharmony_ci           fn r_return_rust_string() -> String;
130e41f4b71Sopenharmony_ci           fn r_return_sum(_: usize, _: usize) -> usize;
131e41f4b71Sopenharmony_ci       }
132e41f4b71Sopenharmony_ci   }
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ci   fn print_message_in_rust(){
135e41f4b71Sopenharmony_ci       println!("Here is a test for cpp call Rust.");
136e41f4b71Sopenharmony_ci   }
137e41f4b71Sopenharmony_ci   fn r_return_shared() -> ffi::Shared {
138e41f4b71Sopenharmony_ci       println!("Here is a message from Rust,test for ffi::Shared:");
139e41f4b71Sopenharmony_ci       ffi::Shared { z: 1996 }
140e41f4b71Sopenharmony_ci   }
141e41f4b71Sopenharmony_ci   fn r_return_primitive() -> usize {
142e41f4b71Sopenharmony_ci       println!("Here is a message from Rust,test for usize:");
143e41f4b71Sopenharmony_ci       1997
144e41f4b71Sopenharmony_ci   }
145e41f4b71Sopenharmony_ci   fn r_return_rust_string() -> String {
146e41f4b71Sopenharmony_ci       println!("Here is a message from Rust,test for String");
147e41f4b71Sopenharmony_ci       "Hello World!".to_owned()
148e41f4b71Sopenharmony_ci   }
149e41f4b71Sopenharmony_ci   fn r_return_sum(n1: usize, n2: usize) -> usize {
150e41f4b71Sopenharmony_ci       println!("Here is a message from Rust,test for {} + {} is:",n1 ,n2);
151e41f4b71Sopenharmony_ci       n1 + n2
152e41f4b71Sopenharmony_ci   }
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci   ```
155e41f4b71Sopenharmony_ci
156e41f4b71Sopenharmony_ci2. Include **lib.rs.h** (converted from **lib.rs** by the CXX tool) in C++ code.
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci   ```c++
159e41f4b71Sopenharmony_ci   #include <iostream>
160e41f4b71Sopenharmony_ci   #include "build/rust/tests/test_cxx/src/lib.rs.h"
161e41f4b71Sopenharmony_ci
162e41f4b71Sopenharmony_ci   int main(int argc, const char* argv[])
163e41f4b71Sopenharmony_ci   {
164e41f4b71Sopenharmony_ci       int a = 2021;
165e41f4b71Sopenharmony_ci       int b = 4;
166e41f4b71Sopenharmony_ci       print_message_in_rust();
167e41f4b71Sopenharmony_ci       std::cout << r_return_primitive() << std::endl;
168e41f4b71Sopenharmony_ci       std::cout << r_return_shared().z << std::endl;
169e41f4b71Sopenharmony_ci       std::cout << std::string(r_return_rust_string()) << std::endl;
170e41f4b71Sopenharmony_ci       std::cout << r_return_sum(a, b) << std::endl;
171e41f4b71Sopenharmony_ci       return 0;
172e41f4b71Sopenharmony_ci   }
173e41f4b71Sopenharmony_ci   ```
174e41f4b71Sopenharmony_ci
175e41f4b71Sopenharmony_ci3. Create the **BUILD.gn** file. The underlying rust_cxx calls the CXX tool to convert the **lib.rs** file into **lib.rs.h** and **lib.rs.cc**. **ohos_rust_static_ffi** implements compilation of the Rust source code, and **ohos_executable** implements compilation of the C++ code.
176e41f4b71Sopenharmony_ci
177e41f4b71Sopenharmony_ci   ```
178e41f4b71Sopenharmony_ci   import("//build/ohos.gni")
179e41f4b71Sopenharmony_ci   import("//build/templates/rust/rust_cxx.gni")
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ci   rust_cxx("test_cxx_exe_gen") {
182e41f4b71Sopenharmony_ci       sources = [ "src/lib.rs" ]
183e41f4b71Sopenharmony_ci   }
184e41f4b71Sopenharmony_ci
185e41f4b71Sopenharmony_ci   ohos_rust_static_ffi("test_cxx_examp_rust") {
186e41f4b71Sopenharmony_ci       sources = [ "src/lib.rs" ]
187e41f4b71Sopenharmony_ci       deps = [ "//build/rust:cxx_rustdeps" ]
188e41f4b71Sopenharmony_ci   }
189e41f4b71Sopenharmony_ci
190e41f4b71Sopenharmony_ci   ohos_executable("test_cxx_exe") {
191e41f4b71Sopenharmony_ci       sources = [ "main.cpp" ]
192e41f4b71Sopenharmony_ci       sources += get_target_outputs(":test_cxx_exe_gen")
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci       include_dirs = [ "${target_gen_dir}" ]
195e41f4b71Sopenharmony_ci       deps = [
196e41f4b71Sopenharmony_ci       ":test_cxx_examp_rust",
197e41f4b71Sopenharmony_ci       ":test_cxx_exe_gen",
198e41f4b71Sopenharmony_ci       "//build/rust:cxx_cppdeps",
199e41f4b71Sopenharmony_ci       ]
200e41f4b71Sopenharmony_ci   }
201e41f4b71Sopenharmony_ci   ```
202e41f4b71Sopenharmony_ci
203e41f4b71Sopenharmony_ci**Verification**
204e41f4b71Sopenharmony_ci![cpp_call_rust](./figures/cpp_call_rust.png)
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci
207e41f4b71Sopenharmony_ci### Calling C++ by Rust
208e41f4b71Sopenharmony_ci
209e41f4b71Sopenharmony_ci1. Create the header file **client_blobstore.h**.
210e41f4b71Sopenharmony_ci
211e41f4b71Sopenharmony_ci   ```c++
212e41f4b71Sopenharmony_ci   #ifndef BUILD_RUST_TESTS_CLIENT_BLOBSTORE_H
213e41f4b71Sopenharmony_ci   #define BUILD_RUST_TESTS_CLIENT_BLOBSTORE_H
214e41f4b71Sopenharmony_ci   #include <memory>
215e41f4b71Sopenharmony_ci   #include "third_party/rust/cxx/include/cxx.h"
216e41f4b71Sopenharmony_ci
217e41f4b71Sopenharmony_ci   namespace nsp_org {
218e41f4b71Sopenharmony_ci   namespace nsp_blobstore {
219e41f4b71Sopenharmony_ci   struct MultiBufs;
220e41f4b71Sopenharmony_ci   struct Metadata_Blob;
221e41f4b71Sopenharmony_ci
222e41f4b71Sopenharmony_ci   class client_blobstore {
223e41f4b71Sopenharmony_ci   public:
224e41f4b71Sopenharmony_ci       client_blobstore();
225e41f4b71Sopenharmony_ci       uint64_t put_buf(MultiBufs &buf) const;
226e41f4b71Sopenharmony_ci       void add_tag(uint64_t blobid, rust::Str add_tag) const;
227e41f4b71Sopenharmony_ci       Metadata_Blob get_metadata(uint64_t blobid) const;
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci   private:
230e41f4b71Sopenharmony_ci       class impl;
231e41f4b71Sopenharmony_ci       std::shared_ptr<impl> impl;
232e41f4b71Sopenharmony_ci   };
233e41f4b71Sopenharmony_ci
234e41f4b71Sopenharmony_ci   std::unique_ptr<client_blobstore> blobstore_client_new();
235e41f4b71Sopenharmony_ci   } // namespace nsp_blobstore
236e41f4b71Sopenharmony_ci   } // namespace nsp_org
237e41f4b71Sopenharmony_ci   #endif
238e41f4b71Sopenharmony_ci   ```
239e41f4b71Sopenharmony_ci
240e41f4b71Sopenharmony_ci2. Create the **client_blobstore.cpp** file.
241e41f4b71Sopenharmony_ci
242e41f4b71Sopenharmony_ci   ```c++
243e41f4b71Sopenharmony_ci   #include <algorithm>
244e41f4b71Sopenharmony_ci   #include <functional>
245e41f4b71Sopenharmony_ci   #include <set>
246e41f4b71Sopenharmony_ci   #include <string>
247e41f4b71Sopenharmony_ci   #include <unordered_map>
248e41f4b71Sopenharmony_ci   #include "src/main.rs.h"
249e41f4b71Sopenharmony_ci   #include "build/rust/tests/test_cxx_rust/include/client_blobstore.h"
250e41f4b71Sopenharmony_ci
251e41f4b71Sopenharmony_ci   namespace nsp_org {
252e41f4b71Sopenharmony_ci   namespace nsp_blobstore {
253e41f4b71Sopenharmony_ci   // Toy implementation of an in-memory nsp_blobstore.
254e41f4b71Sopenharmony_ci   //
255e41f4b71Sopenharmony_ci   // The real implementation of client_blobstore could be a large complex C++
256e41f4b71Sopenharmony_ci   // library.
257e41f4b71Sopenharmony_ci   class client_blobstore::impl {
258e41f4b71Sopenharmony_ci       friend client_blobstore;
259e41f4b71Sopenharmony_ci       using Blob = struct {
260e41f4b71Sopenharmony_ci           std::string data;
261e41f4b71Sopenharmony_ci           std::set<std::string> tags;
262e41f4b71Sopenharmony_ci       };
263e41f4b71Sopenharmony_ci       std::unordered_map<uint64_t, Blob> blobs;
264e41f4b71Sopenharmony_ci   };
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci   client_blobstore::client_blobstore() : impl(new class client_blobstore::impl) {}
267e41f4b71Sopenharmony_ci
268e41f4b71Sopenharmony_ci   // Upload a new blob and return a blobid that serves as a handle to the blob.
269e41f4b71Sopenharmony_ci   uint64_t client_blobstore::put_buf(MultiBufs &buf) const
270e41f4b71Sopenharmony_ci   {
271e41f4b71Sopenharmony_ci       std::string contents;
272e41f4b71Sopenharmony_ci
273e41f4b71Sopenharmony_ci       // Traverse the caller's res_chunk iterator.
274e41f4b71Sopenharmony_ci       //
275e41f4b71Sopenharmony_ci       // In reality there might be sophisticated batching of chunks and/or parallel
276e41f4b71Sopenharmony_ci       // upload implemented by the nsp_blobstore's C++ client.
277e41f4b71Sopenharmony_ci       while (true) {
278e41f4b71Sopenharmony_ci           auto res_chunk = next_chunk(buf);
279e41f4b71Sopenharmony_ci           if (res_chunk.size() == 0) {
280e41f4b71Sopenharmony_ci           break;
281e41f4b71Sopenharmony_ci           }
282e41f4b71Sopenharmony_ci           contents.append(reinterpret_cast<const char *>(res_chunk.data()), res_chunk.size());
283e41f4b71Sopenharmony_ci       }
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci       // Insert into map and provide caller the handle.
286e41f4b71Sopenharmony_ci       auto res = std::hash<std::string> {} (contents);
287e41f4b71Sopenharmony_ci       impl->blobs[res] = {std::move(contents), {}};
288e41f4b71Sopenharmony_ci       return res;
289e41f4b71Sopenharmony_ci   }
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci   // Add add_tag to an existing blob.
292e41f4b71Sopenharmony_ci   void client_blobstore::add_tag(uint64_t blobid, rust::Str add_tag) const
293e41f4b71Sopenharmony_ci   {
294e41f4b71Sopenharmony_ci       impl->blobs[blobid].tags.emplace(add_tag);
295e41f4b71Sopenharmony_ci   }
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci   // Retrieve get_metadata about a blob.
298e41f4b71Sopenharmony_ci   Metadata_Blob client_blobstore::get_metadata(uint64_t blobid) const
299e41f4b71Sopenharmony_ci   {
300e41f4b71Sopenharmony_ci       Metadata_Blob get_metadata {};
301e41f4b71Sopenharmony_ci       auto blob = impl->blobs.find(blobid);
302e41f4b71Sopenharmony_ci       if (blob != impl->blobs.end()) {
303e41f4b71Sopenharmony_ci           get_metadata.size = blob->second.data.size();
304e41f4b71Sopenharmony_ci           std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
305e41f4b71Sopenharmony_ci               [&](auto &t) { get_metadata.tags.emplace_back(t); });
306e41f4b71Sopenharmony_ci       }
307e41f4b71Sopenharmony_ci       return get_metadata;
308e41f4b71Sopenharmony_ci   }
309e41f4b71Sopenharmony_ci
310e41f4b71Sopenharmony_ci   std::unique_ptr<client_blobstore> blobstore_client_new()
311e41f4b71Sopenharmony_ci   {
312e41f4b71Sopenharmony_ci       return std::make_unique<client_blobstore>();
313e41f4b71Sopenharmony_ci   }
314e41f4b71Sopenharmony_ci   } // namespace nsp_blobstore
315e41f4b71Sopenharmony_ci   } // namespace nsp_org
316e41f4b71Sopenharmony_ci
317e41f4b71Sopenharmony_ci   ```
318e41f4b71Sopenharmony_ci
319e41f4b71Sopenharmony_ci3. In **ffi** of the **main.rs** file, use the macro **includes!** to import the header file **client_blobstore.h**. Then, the **main()** function of Rust can call the C++ interfaces in ffi mode.
320e41f4b71Sopenharmony_ci
321e41f4b71Sopenharmony_ci   ```rust
322e41f4b71Sopenharmony_ci   //! test_cxx_rust
323e41f4b71Sopenharmony_ci   #[cxx::bridge(namespace = "nsp_org::nsp_blobstore")]
324e41f4b71Sopenharmony_ci   mod ffi {
325e41f4b71Sopenharmony_ci       // Shared structs with fields visible to both languages.
326e41f4b71Sopenharmony_ci       struct Metadata_Blob {
327e41f4b71Sopenharmony_ci           size: usize,
328e41f4b71Sopenharmony_ci           tags: Vec<String>,
329e41f4b71Sopenharmony_ci       }
330e41f4b71Sopenharmony_ci
331e41f4b71Sopenharmony_ci       // Rust types and signatures exposed to C++.
332e41f4b71Sopenharmony_ci       extern "Rust" {
333e41f4b71Sopenharmony_ci           type MultiBufs;
334e41f4b71Sopenharmony_ci
335e41f4b71Sopenharmony_ci           fn next_chunk(buf: &mut MultiBufs) -> &[u8];
336e41f4b71Sopenharmony_ci       }
337e41f4b71Sopenharmony_ci
338e41f4b71Sopenharmony_ci       // C++ types and signatures exposed to Rust.
339e41f4b71Sopenharmony_ci       unsafe extern "C++" {
340e41f4b71Sopenharmony_ci           include!("build/rust/tests/test_cxx_rust/include/client_blobstore.h");
341e41f4b71Sopenharmony_ci
342e41f4b71Sopenharmony_ci           type client_blobstore;
343e41f4b71Sopenharmony_ci
344e41f4b71Sopenharmony_ci           fn blobstore_client_new() -> UniquePtr<client_blobstore>;
345e41f4b71Sopenharmony_ci           fn put_buf(&self, parts: &mut MultiBufs) -> u64;
346e41f4b71Sopenharmony_ci           fn add_tag(&self, blobid: u64, add_tag: &str);
347e41f4b71Sopenharmony_ci           fn get_metadata(&self, blobid: u64) -> Metadata_Blob;
348e41f4b71Sopenharmony_ci       }
349e41f4b71Sopenharmony_ci   }
350e41f4b71Sopenharmony_ci
351e41f4b71Sopenharmony_ci   // An iterator over contiguous chunks of a discontiguous file object.
352e41f4b71Sopenharmony_ci   //
353e41f4b71Sopenharmony_ci   // Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
354e41f4b71Sopenharmony_ci   // over some more complex Rust data structure like a rope, or maybe loading
355e41f4b71Sopenharmony_ci   // chunks lazily from somewhere.
356e41f4b71Sopenharmony_ci   /// pub struct MultiBufs
357e41f4b71Sopenharmony_ci   pub struct MultiBufs {
358e41f4b71Sopenharmony_ci       chunks: Vec<Vec<u8>>,
359e41f4b71Sopenharmony_ci       pos: usize,
360e41f4b71Sopenharmony_ci   }
361e41f4b71Sopenharmony_ci   /// pub fn next_chunk
362e41f4b71Sopenharmony_ci   pub fn next_chunk(buf: &mut MultiBufs) -> &[u8] {
363e41f4b71Sopenharmony_ci       let next = buf.chunks.get(buf.pos);
364e41f4b71Sopenharmony_ci       buf.pos += 1;
365e41f4b71Sopenharmony_ci       next.map_or(&[], Vec::as_slice)
366e41f4b71Sopenharmony_ci   }
367e41f4b71Sopenharmony_ci
368e41f4b71Sopenharmony_ci   /// fn main()
369e41f4b71Sopenharmony_ci   fn main() {
370e41f4b71Sopenharmony_ci       let client = ffi::blobstore_client_new();
371e41f4b71Sopenharmony_ci
372e41f4b71Sopenharmony_ci       // Upload a blob.
373e41f4b71Sopenharmony_ci       let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
374e41f4b71Sopenharmony_ci       let mut buf = MultiBufs { chunks, pos: 0 };
375e41f4b71Sopenharmony_ci       let blobid = client.put_buf(&mut buf);
376e41f4b71Sopenharmony_ci       println!("This is a test for Rust call cpp:");
377e41f4b71Sopenharmony_ci       println!("blobid = {}", blobid);
378e41f4b71Sopenharmony_ci
379e41f4b71Sopenharmony_ci       // Add a add_tag.
380e41f4b71Sopenharmony_ci       client.add_tag(blobid, "rust");
381e41f4b71Sopenharmony_ci
382e41f4b71Sopenharmony_ci       // Read back the tags.
383e41f4b71Sopenharmony_ci       let get_metadata = client.get_metadata(blobid);
384e41f4b71Sopenharmony_ci       println!("tags = {:?}", get_metadata.tags);
385e41f4b71Sopenharmony_ci   }
386e41f4b71Sopenharmony_ci   ```
387e41f4b71Sopenharmony_ci
388e41f4b71Sopenharmony_ci4. Create the **BUILD.gn** file. Use CXX to convert **main.rs** into **lib.rs.h** and **lib.rs.cc**, which are used as the source code of **test_cxx_rust_staticlib**. Compile Rust **main.rs**, and add the dependency **test_cxx_rust_staticlib**.
389e41f4b71Sopenharmony_ci
390e41f4b71Sopenharmony_ci   ```
391e41f4b71Sopenharmony_ci   import("//build/ohos.gni")
392e41f4b71Sopenharmony_ci
393e41f4b71Sopenharmony_ci   rust_cxx("test_cxx_rust_gen") {
394e41f4b71Sopenharmony_ci     sources = [ "src/main.rs" ]
395e41f4b71Sopenharmony_ci   }
396e41f4b71Sopenharmony_ci
397e41f4b71Sopenharmony_ci   ohos_static_library("test_cxx_rust_staticlib") {
398e41f4b71Sopenharmony_ci     sources = [ "src/client_blobstore.cpp" ]
399e41f4b71Sopenharmony_ci     sources += get_target_outputs(":test_cxx_rust_gen")
400e41f4b71Sopenharmony_ci     include_dirs = [
401e41f4b71Sopenharmony_ci       "${target_gen_dir}",
402e41f4b71Sopenharmony_ci       "//third_party/rust/cxx/v1/crate/include",
403e41f4b71Sopenharmony_ci       "include",
404e41f4b71Sopenharmony_ci     ]
405e41f4b71Sopenharmony_ci     deps = [
406e41f4b71Sopenharmony_ci       ":test_cxx_rust_gen",
407e41f4b71Sopenharmony_ci       "//build/rust:cxx_cppdeps",
408e41f4b71Sopenharmony_ci     ]
409e41f4b71Sopenharmony_ci   }
410e41f4b71Sopenharmony_ci
411e41f4b71Sopenharmony_ci   ohos_rust_executable("test_cxx_rust") {
412e41f4b71Sopenharmony_ci     sources = [ "src/main.rs" ]
413e41f4b71Sopenharmony_ci     deps = [
414e41f4b71Sopenharmony_ci       ":test_cxx_rust_staticlib",
415e41f4b71Sopenharmony_ci       "//build/rust:cxx_rustdeps",
416e41f4b71Sopenharmony_ci     ]
417e41f4b71Sopenharmony_ci   }
418e41f4b71Sopenharmony_ci   ```
419e41f4b71Sopenharmony_ci
420e41f4b71Sopenharmony_ci**Verification**
421e41f4b71Sopenharmony_ci![rust_call_cpp](./figures/rust_call_cpp.png)
422