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 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 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 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 422