133d722a9Sopenharmony_ciCXX — Rust和C++之间的安全FFI
233d722a9Sopenharmony_ci=========================================
333d722a9Sopenharmony_ci
433d722a9Sopenharmony_ci[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/CXX-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/CXX)
533d722a9Sopenharmony_ci[<img alt="crates.io" src="https://img.shields.io/crates/v/CXX.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/CXX)
633d722a9Sopenharmony_ci[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-CXX-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/cxx)
733d722a9Sopenharmony_ci[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/CXX/ci.yml" height="20">](https://github.com/dtolnay/CXX)
833d722a9Sopenharmony_ci
933d722a9Sopenharmony_ci
1033d722a9Sopenharmony_ci## 引入背景
1133d722a9Sopenharmony_ci
1233d722a9Sopenharmony_ci
1333d722a9Sopenharmony_ciCXX工具提供了一种安全的互相调用机制,可以实现rust和C++的互相调用。
1433d722a9Sopenharmony_ci
1533d722a9Sopenharmony_ciCXX通过FFI(Foreign Function Interface)和函数签名的形式来实现接口和类型声明,并对类型和函数签名进行静态分析,以维护Rust和C++的不变量和要求。
1633d722a9Sopenharmony_ci
1733d722a9Sopenharmony_ci<br>
1833d722a9Sopenharmony_ci
1933d722a9Sopenharmony_ci## CXX工具在OH上的使用指导
2033d722a9Sopenharmony_ci
2133d722a9Sopenharmony_ci### C++调用Rust接口
2233d722a9Sopenharmony_ci
2333d722a9Sopenharmony_ci1. 在Rust侧文件lib.rs里mod ffi写清楚需要调用的C++接口,并将接口包含在extern "Rust"里面,暴露给C++侧使用。
2433d722a9Sopenharmony_ci
2533d722a9Sopenharmony_ci   ```rust
2633d722a9Sopenharmony_ci   //! #[cxx::bridge]
2733d722a9Sopenharmony_ci   #[cxx::bridge]
2833d722a9Sopenharmony_ci   mod ffi{
2933d722a9Sopenharmony_ci       #![allow(dead_code)]
3033d722a9Sopenharmony_ci       #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
3133d722a9Sopenharmony_ci       struct Shared {
3233d722a9Sopenharmony_ci           z: usize,
3333d722a9Sopenharmony_ci       }
3433d722a9Sopenharmony_ci       extern "Rust"{
3533d722a9Sopenharmony_ci           fn print_message_in_rust();
3633d722a9Sopenharmony_ci           fn r_return_primitive() -> usize;
3733d722a9Sopenharmony_ci           fn r_return_shared() -> Shared;
3833d722a9Sopenharmony_ci           fn r_return_rust_string() -> String;
3933d722a9Sopenharmony_ci           fn r_return_sum(_: usize, _: usize) -> usize;
4033d722a9Sopenharmony_ci       }
4133d722a9Sopenharmony_ci   }
4233d722a9Sopenharmony_ci
4333d722a9Sopenharmony_ci   fn print_message_in_rust(){
4433d722a9Sopenharmony_ci       println!("Here is a test for cpp call Rust.");
4533d722a9Sopenharmony_ci   }
4633d722a9Sopenharmony_ci   fn r_return_shared() -> ffi::Shared {
4733d722a9Sopenharmony_ci       println!("Here is a message from Rust,test for ffi::Shared:");
4833d722a9Sopenharmony_ci       ffi::Shared { z: 1996 }
4933d722a9Sopenharmony_ci   }
5033d722a9Sopenharmony_ci   fn r_return_primitive() -> usize {
5133d722a9Sopenharmony_ci       println!("Here is a message from Rust,test for usize:");
5233d722a9Sopenharmony_ci       1997
5333d722a9Sopenharmony_ci   }
5433d722a9Sopenharmony_ci   fn r_return_rust_string() -> String {
5533d722a9Sopenharmony_ci       println!("Here is a message from Rust,test for String");
5633d722a9Sopenharmony_ci       "Hello World!".to_owned()
5733d722a9Sopenharmony_ci   }
5833d722a9Sopenharmony_ci   fn r_return_sum(n1: usize, n2: usize) -> usize {
5933d722a9Sopenharmony_ci       println!("Here is a message from Rust,test for {} + {} is:",n1 ,n2);
6033d722a9Sopenharmony_ci       n1 + n2
6133d722a9Sopenharmony_ci   }
6233d722a9Sopenharmony_ci
6333d722a9Sopenharmony_ci   ```
6433d722a9Sopenharmony_ci
6533d722a9Sopenharmony_ci2. C++侧将cxx工具转换出来的lib.rs.h包含进来,就可以使用C++侧的接口。
6633d722a9Sopenharmony_ci
6733d722a9Sopenharmony_ci   ```c++
6833d722a9Sopenharmony_ci   #include <iostream>
6933d722a9Sopenharmony_ci   #include "build/rust/tests/test_cxx/src/lib.rs.h"
7033d722a9Sopenharmony_ci
7133d722a9Sopenharmony_ci   int main(int argc, const char* argv[])
7233d722a9Sopenharmony_ci   {
7333d722a9Sopenharmony_ci       int a = 2021;
7433d722a9Sopenharmony_ci       int b = 4;
7533d722a9Sopenharmony_ci       print_message_in_rust();
7633d722a9Sopenharmony_ci       std::cout << r_return_primitive() << std::endl;
7733d722a9Sopenharmony_ci       std::cout << r_return_shared().z << std::endl;
7833d722a9Sopenharmony_ci       std::cout << std::string(r_return_rust_string()) << std::endl;
7933d722a9Sopenharmony_ci       std::cout << r_return_sum(a, b) << std::endl;
8033d722a9Sopenharmony_ci       return 0;
8133d722a9Sopenharmony_ci   }
8233d722a9Sopenharmony_ci   ```
8333d722a9Sopenharmony_ci
8433d722a9Sopenharmony_ci3. 添加构建文件BUILD.gn。rust_cxx底层调用CXX工具将lib.rs文件转换成lib.rs.hlib.rs.cc文件,ohos_rust_static_ffi实现Rust侧源码的编译,ohos_executable实现C++侧代码的编译。
8533d722a9Sopenharmony_ci
8633d722a9Sopenharmony_ci   ```
8733d722a9Sopenharmony_ci   import("//build/ohos.gni")
8833d722a9Sopenharmony_ci   import("//build/templates/rust/rust_cxx.gni")
8933d722a9Sopenharmony_ci
9033d722a9Sopenharmony_ci   rust_cxx("test_cxx_exe_gen") {
9133d722a9Sopenharmony_ci       sources = [ "src/lib.rs" ]
9233d722a9Sopenharmony_ci   }
9333d722a9Sopenharmony_ci
9433d722a9Sopenharmony_ci   ohos_rust_static_ffi("test_cxx_examp_rust") {
9533d722a9Sopenharmony_ci       sources = [ "src/lib.rs" ]
9633d722a9Sopenharmony_ci       deps = [ "//build/rust:cxx_rustdeps" ]
9733d722a9Sopenharmony_ci   }
9833d722a9Sopenharmony_ci
9933d722a9Sopenharmony_ci   ohos_executable("test_cxx_exe") {
10033d722a9Sopenharmony_ci       sources = [ "main.cpp" ]
10133d722a9Sopenharmony_ci       sources += get_target_outputs(":test_cxx_exe_gen")
10233d722a9Sopenharmony_ci
10333d722a9Sopenharmony_ci       include_dirs = [ "${target_gen_dir}" ]
10433d722a9Sopenharmony_ci       deps = [
10533d722a9Sopenharmony_ci       ":test_cxx_examp_rust",
10633d722a9Sopenharmony_ci       ":test_cxx_exe_gen",
10733d722a9Sopenharmony_ci       "//build/rust:cxx_cppdeps",
10833d722a9Sopenharmony_ci       ]
10933d722a9Sopenharmony_ci   }
11033d722a9Sopenharmony_ci   ```
11133d722a9Sopenharmony_ci
11233d722a9Sopenharmony_ci**调测验证**
11333d722a9Sopenharmony_ci![cpp_call_rust](./cpp_call_rust.png)
11433d722a9Sopenharmony_ci
11533d722a9Sopenharmony_ci
11633d722a9Sopenharmony_ci### Rust调用C++
11733d722a9Sopenharmony_ci
11833d722a9Sopenharmony_ci1. 添加头文件client_blobstore.h11933d722a9Sopenharmony_ci
12033d722a9Sopenharmony_ci   ```c++
12133d722a9Sopenharmony_ci   #ifndef BUILD_RUST_TESTS_CLIENT_BLOBSTORE_H
12233d722a9Sopenharmony_ci   #define BUILD_RUST_TESTS_CLIENT_BLOBSTORE_H
12333d722a9Sopenharmony_ci   #include <memory>
12433d722a9Sopenharmony_ci   #include "third_party/rust/cxx/include/cxx.h"
12533d722a9Sopenharmony_ci
12633d722a9Sopenharmony_ci   namespace nsp_org {
12733d722a9Sopenharmony_ci   namespace nsp_blobstore {
12833d722a9Sopenharmony_ci   struct MultiBufs;
12933d722a9Sopenharmony_ci   struct Metadata_Blob;
13033d722a9Sopenharmony_ci
13133d722a9Sopenharmony_ci   class client_blobstore {
13233d722a9Sopenharmony_ci   public:
13333d722a9Sopenharmony_ci       client_blobstore();
13433d722a9Sopenharmony_ci       uint64_t put_buf(MultiBufs &buf) const;
13533d722a9Sopenharmony_ci       void add_tag(uint64_t blobid, rust::Str add_tag) const;
13633d722a9Sopenharmony_ci       Metadata_Blob get_metadata(uint64_t blobid) const;
13733d722a9Sopenharmony_ci
13833d722a9Sopenharmony_ci   private:
13933d722a9Sopenharmony_ci       class impl;
14033d722a9Sopenharmony_ci       std::shared_ptr<impl> impl;
14133d722a9Sopenharmony_ci   };
14233d722a9Sopenharmony_ci
14333d722a9Sopenharmony_ci   std::unique_ptr<client_blobstore> blobstore_client_new();
14433d722a9Sopenharmony_ci   } // namespace nsp_blobstore
14533d722a9Sopenharmony_ci   } // namespace nsp_org
14633d722a9Sopenharmony_ci   #endif
14733d722a9Sopenharmony_ci   ```
14833d722a9Sopenharmony_ci
14933d722a9Sopenharmony_ci2. 添加cpp文件client_blobstore.cpp15033d722a9Sopenharmony_ci
15133d722a9Sopenharmony_ci   ```c++
15233d722a9Sopenharmony_ci   #include <algorithm>
15333d722a9Sopenharmony_ci   #include <functional>
15433d722a9Sopenharmony_ci   #include <set>
15533d722a9Sopenharmony_ci   #include <string>
15633d722a9Sopenharmony_ci   #include <unordered_map>
15733d722a9Sopenharmony_ci   #include "src/main.rs.h"
15833d722a9Sopenharmony_ci   #include "build/rust/tests/test_cxx_rust/include/client_blobstore.h"
15933d722a9Sopenharmony_ci
16033d722a9Sopenharmony_ci   namespace nsp_org {
16133d722a9Sopenharmony_ci   namespace nsp_blobstore {
16233d722a9Sopenharmony_ci   // Toy implementation of an in-memory nsp_blobstore.
16333d722a9Sopenharmony_ci   //
16433d722a9Sopenharmony_ci   // In reality the implementation of client_blobstore could be a large complex C++
16533d722a9Sopenharmony_ci   // library.
16633d722a9Sopenharmony_ci   class client_blobstore::impl {
16733d722a9Sopenharmony_ci       friend client_blobstore;
16833d722a9Sopenharmony_ci       using Blob = struct {
16933d722a9Sopenharmony_ci           std::string data;
17033d722a9Sopenharmony_ci           std::set<std::string> tags;
17133d722a9Sopenharmony_ci       };
17233d722a9Sopenharmony_ci       std::unordered_map<uint64_t, Blob> blobs;
17333d722a9Sopenharmony_ci   };
17433d722a9Sopenharmony_ci
17533d722a9Sopenharmony_ci   client_blobstore::client_blobstore() : impl(new class client_blobstore::impl) {}
17633d722a9Sopenharmony_ci
17733d722a9Sopenharmony_ci   // Upload a new blob and return a blobid that serves as a handle to the blob.
17833d722a9Sopenharmony_ci   uint64_t client_blobstore::put_buf(MultiBufs &buf) const
17933d722a9Sopenharmony_ci   {
18033d722a9Sopenharmony_ci       std::string contents;
18133d722a9Sopenharmony_ci
18233d722a9Sopenharmony_ci       // Traverse the caller's res_chunk iterator.
18333d722a9Sopenharmony_ci       //
18433d722a9Sopenharmony_ci       // In reality there might be sophisticated batching of chunks and/or parallel
18533d722a9Sopenharmony_ci       // upload implemented by the nsp_blobstore's C++ client.
18633d722a9Sopenharmony_ci       while (true) {
18733d722a9Sopenharmony_ci           auto res_chunk = next_chunk(buf);
18833d722a9Sopenharmony_ci           if (res_chunk.size() == 0) {
18933d722a9Sopenharmony_ci           break;
19033d722a9Sopenharmony_ci           }
19133d722a9Sopenharmony_ci           contents.append(reinterpret_cast<const char *>(res_chunk.data()), res_chunk.size());
19233d722a9Sopenharmony_ci       }
19333d722a9Sopenharmony_ci
19433d722a9Sopenharmony_ci       // Insert into map and provide caller the handle.
19533d722a9Sopenharmony_ci       auto res = std::hash<std::string> {} (contents);
19633d722a9Sopenharmony_ci       impl->blobs[res] = {std::move(contents), {}};
19733d722a9Sopenharmony_ci       return res;
19833d722a9Sopenharmony_ci   }
19933d722a9Sopenharmony_ci
20033d722a9Sopenharmony_ci   // Add add_tag to an existing blob.
20133d722a9Sopenharmony_ci   void client_blobstore::add_tag(uint64_t blobid, rust::Str add_tag) const
20233d722a9Sopenharmony_ci   {
20333d722a9Sopenharmony_ci       impl->blobs[blobid].tags.emplace(add_tag);
20433d722a9Sopenharmony_ci   }
20533d722a9Sopenharmony_ci
20633d722a9Sopenharmony_ci   // Retrieve get_metadata about a blob.
20733d722a9Sopenharmony_ci   Metadata_Blob client_blobstore::get_metadata(uint64_t blobid) const
20833d722a9Sopenharmony_ci   {
20933d722a9Sopenharmony_ci       Metadata_Blob get_metadata {};
21033d722a9Sopenharmony_ci       auto blob = impl->blobs.find(blobid);
21133d722a9Sopenharmony_ci       if (blob != impl->blobs.end()) {
21233d722a9Sopenharmony_ci           get_metadata.size = blob->second.data.size();
21333d722a9Sopenharmony_ci           std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
21433d722a9Sopenharmony_ci               [&](auto &t) { get_metadata.tags.emplace_back(t); });
21533d722a9Sopenharmony_ci       }
21633d722a9Sopenharmony_ci       return get_metadata;
21733d722a9Sopenharmony_ci   }
21833d722a9Sopenharmony_ci
21933d722a9Sopenharmony_ci   std::unique_ptr<client_blobstore> blobstore_client_new()
22033d722a9Sopenharmony_ci   {
22133d722a9Sopenharmony_ci       return std::make_unique<client_blobstore>();
22233d722a9Sopenharmony_ci   }
22333d722a9Sopenharmony_ci   } // namespace nsp_blobstore
22433d722a9Sopenharmony_ci   } // namespace nsp_org
22533d722a9Sopenharmony_ci
22633d722a9Sopenharmony_ci   ```
22733d722a9Sopenharmony_ci
22833d722a9Sopenharmony_ci3. main.rs文件,在main.rs文件的ffi里面,通过宏include!将头文件client_blobstore.h引入进来,从而在Rust的main函数里面就可以通过ffi的方式调用C++的接口。
22933d722a9Sopenharmony_ci
23033d722a9Sopenharmony_ci   ```rust
23133d722a9Sopenharmony_ci   //! test_cxx_rust
23233d722a9Sopenharmony_ci   #[cxx::bridge(namespace = "nsp_org::nsp_blobstore")]
23333d722a9Sopenharmony_ci   mod ffi {
23433d722a9Sopenharmony_ci       // Shared structs with fields visible to both languages.
23533d722a9Sopenharmony_ci       struct Metadata_Blob {
23633d722a9Sopenharmony_ci           size: usize,
23733d722a9Sopenharmony_ci           tags: Vec<String>,
23833d722a9Sopenharmony_ci       }
23933d722a9Sopenharmony_ci
24033d722a9Sopenharmony_ci       // Rust types and signatures exposed to C++.
24133d722a9Sopenharmony_ci       extern "Rust" {
24233d722a9Sopenharmony_ci           type MultiBufs;
24333d722a9Sopenharmony_ci
24433d722a9Sopenharmony_ci           fn next_chunk(buf: &mut MultiBufs) -> &[u8];
24533d722a9Sopenharmony_ci       }
24633d722a9Sopenharmony_ci
24733d722a9Sopenharmony_ci       // C++ types and signatures exposed to Rust.
24833d722a9Sopenharmony_ci       unsafe extern "C++" {
24933d722a9Sopenharmony_ci           include!("build/rust/tests/test_cxx_rust/include/client_blobstore.h");
25033d722a9Sopenharmony_ci
25133d722a9Sopenharmony_ci           type client_blobstore;
25233d722a9Sopenharmony_ci
25333d722a9Sopenharmony_ci           fn blobstore_client_new() -> UniquePtr<client_blobstore>;
25433d722a9Sopenharmony_ci           fn put_buf(&self, parts: &mut MultiBufs) -> u64;
25533d722a9Sopenharmony_ci           fn add_tag(&self, blobid: u64, add_tag: &str);
25633d722a9Sopenharmony_ci           fn get_metadata(&self, blobid: u64) -> Metadata_Blob;
25733d722a9Sopenharmony_ci       }
25833d722a9Sopenharmony_ci   }
25933d722a9Sopenharmony_ci
26033d722a9Sopenharmony_ci   // An iterator over contiguous chunks of a discontiguous file object.
26133d722a9Sopenharmony_ci   //
26233d722a9Sopenharmony_ci   // Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
26333d722a9Sopenharmony_ci   // over some more complex Rust data structure like a rope, or maybe loading
26433d722a9Sopenharmony_ci   // chunks lazily from somewhere.
26533d722a9Sopenharmony_ci   /// pub struct MultiBufs
26633d722a9Sopenharmony_ci   pub struct MultiBufs {
26733d722a9Sopenharmony_ci       chunks: Vec<Vec<u8>>,
26833d722a9Sopenharmony_ci       pos: usize,
26933d722a9Sopenharmony_ci   }
27033d722a9Sopenharmony_ci   /// pub fn next_chunk
27133d722a9Sopenharmony_ci   pub fn next_chunk(buf: &mut MultiBufs) -> &[u8] {
27233d722a9Sopenharmony_ci       let next = buf.chunks.get(buf.pos);
27333d722a9Sopenharmony_ci       buf.pos += 1;
27433d722a9Sopenharmony_ci       next.map_or(&[], Vec::as_slice)
27533d722a9Sopenharmony_ci   }
27633d722a9Sopenharmony_ci
27733d722a9Sopenharmony_ci   /// fn main()
27833d722a9Sopenharmony_ci   fn main() {
27933d722a9Sopenharmony_ci       let client = ffi::blobstore_client_new();
28033d722a9Sopenharmony_ci
28133d722a9Sopenharmony_ci       // Upload a blob.
28233d722a9Sopenharmony_ci       let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
28333d722a9Sopenharmony_ci       let mut buf = MultiBufs { chunks, pos: 0 };
28433d722a9Sopenharmony_ci       let blobid = client.put_buf(&mut buf);
28533d722a9Sopenharmony_ci       println!("This is a test for Rust call cpp:");
28633d722a9Sopenharmony_ci       println!("blobid = {}", blobid);
28733d722a9Sopenharmony_ci
28833d722a9Sopenharmony_ci       // Add a add_tag.
28933d722a9Sopenharmony_ci       client.add_tag(blobid, "rust");
29033d722a9Sopenharmony_ci
29133d722a9Sopenharmony_ci       // Read back the tags.
29233d722a9Sopenharmony_ci       let get_metadata = client.get_metadata(blobid);
29333d722a9Sopenharmony_ci       println!("tags = {:?}", get_metadata.tags);
29433d722a9Sopenharmony_ci   }
29533d722a9Sopenharmony_ci   ```
29633d722a9Sopenharmony_ci
29733d722a9Sopenharmony_ci4. 添加构建文件BUILD.gn。使用CXX将main.rs转换成lib.rs.hlib.rs.cc,同时将产物作为test_cxx_rust_staticlib的源码,编译Rust源码main.rs并将test_cxx_rust_staticlib依赖进来。
29833d722a9Sopenharmony_ci
29933d722a9Sopenharmony_ci   ```
30033d722a9Sopenharmony_ci   import("//build/ohos.gni")
30133d722a9Sopenharmony_ci
30233d722a9Sopenharmony_ci   rust_cxx("test_cxx_rust_gen") {
30333d722a9Sopenharmony_ci     sources = [ "src/main.rs" ]
30433d722a9Sopenharmony_ci   }
30533d722a9Sopenharmony_ci
30633d722a9Sopenharmony_ci   ohos_static_library("test_cxx_rust_staticlib") {
30733d722a9Sopenharmony_ci     sources = [ "src/client_blobstore.cpp" ]
30833d722a9Sopenharmony_ci     sources += get_target_outputs(":test_cxx_rust_gen")
30933d722a9Sopenharmony_ci     include_dirs = [
31033d722a9Sopenharmony_ci       "${target_gen_dir}",
31133d722a9Sopenharmony_ci       "//third_party/rust/cxx/v1/crate/include",
31233d722a9Sopenharmony_ci       "include",
31333d722a9Sopenharmony_ci     ]
31433d722a9Sopenharmony_ci     deps = [
31533d722a9Sopenharmony_ci       ":test_cxx_rust_gen",
31633d722a9Sopenharmony_ci       "//build/rust:cxx_cppdeps",
31733d722a9Sopenharmony_ci     ]
31833d722a9Sopenharmony_ci   }
31933d722a9Sopenharmony_ci
32033d722a9Sopenharmony_ci   ohos_rust_executable("test_cxx_rust") {
32133d722a9Sopenharmony_ci     sources = [ "src/main.rs" ]
32233d722a9Sopenharmony_ci     deps = [
32333d722a9Sopenharmony_ci       ":test_cxx_rust_staticlib",
32433d722a9Sopenharmony_ci       "//build/rust:cxx_rustdeps",
32533d722a9Sopenharmony_ci     ]
32633d722a9Sopenharmony_ci   }
32733d722a9Sopenharmony_ci   ```
32833d722a9Sopenharmony_ci
32933d722a9Sopenharmony_ci**调测验证**
33033d722a9Sopenharmony_ci![rust_call_cpp](./rust_call_cpp.png)
33133d722a9Sopenharmony_ci
33233d722a9Sopenharmony_ci<br>
33333d722a9Sopenharmony_ci
33433d722a9Sopenharmony_ci
33533d722a9Sopenharmony_ci
33633d722a9Sopenharmony_ci## 与bindgen的对比
33733d722a9Sopenharmony_ci
33833d722a9Sopenharmony_cibindgen主要用来实现rust代码对c接口的单向调用;CXX工具可以实现rust和C++的互相调用。
33933d722a9Sopenharmony_ci
34033d722a9Sopenharmony_ci<br>
34133d722a9Sopenharmony_ci
34233d722a9Sopenharmony_ci## 基于cargo的构建
34333d722a9Sopenharmony_ci
34433d722a9Sopenharmony_ci对于由Cargo的构建,需要使用一个构建脚本来运行CXX的C++代码生成器。
34533d722a9Sopenharmony_ci
34633d722a9Sopenharmony_ci典型的构建脚本如下:
34733d722a9Sopenharmony_ci
34833d722a9Sopenharmony_ci[`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
34933d722a9Sopenharmony_ci
35033d722a9Sopenharmony_ci```toml
35133d722a9Sopenharmony_ci# Cargo.toml
35233d722a9Sopenharmony_ci
35333d722a9Sopenharmony_ci[build-dependencies]
35433d722a9Sopenharmony_ciCXX-build = "1.0"
35533d722a9Sopenharmony_ci```
35633d722a9Sopenharmony_ci
35733d722a9Sopenharmony_ci```rust
35833d722a9Sopenharmony_ci// build.rs
35933d722a9Sopenharmony_ci
36033d722a9Sopenharmony_cifn main() {
36133d722a9Sopenharmony_ci    CXX_build::bridge("src/main.rs")  // returns a cc::Build
36233d722a9Sopenharmony_ci        .file("src/demo.cc")
36333d722a9Sopenharmony_ci        .flag_if_supported("-std=C++11")
36433d722a9Sopenharmony_ci        .compile("cxxbridge-demo");
36533d722a9Sopenharmony_ci
36633d722a9Sopenharmony_ci    println!("cargo:rerun-if-changed=src/main.rs");
36733d722a9Sopenharmony_ci    println!("cargo:rerun-if-changed=src/demo.cc");
36833d722a9Sopenharmony_ci    println!("cargo:rerun-if-changed=include/demo.h");
36933d722a9Sopenharmony_ci}
37033d722a9Sopenharmony_ci```
37133d722a9Sopenharmony_ci
37233d722a9Sopenharmony_ci<br>
37333d722a9Sopenharmony_ci
37433d722a9Sopenharmony_ci## 基于非cargo的构建
37533d722a9Sopenharmony_ci
37633d722a9Sopenharmony_ci对于在非Cargo构建中的使用,如Bazel或Buck,CXX提供了另一种方式产生C++侧的头文件和源代码文件,作为一个独立的命令行工具使用。
37733d722a9Sopenharmony_ci
37833d722a9Sopenharmony_ci```bash
37933d722a9Sopenharmony_ci$ cargo install cxxbridge-cmd
38033d722a9Sopenharmony_ci$ cxxbridge src/main.rs --header > path/to/mybridge.h
38133d722a9Sopenharmony_ci$ cxxbridge src/main.rs > path/to/mybridge.cc
38233d722a9Sopenharmony_ci```
38333d722a9Sopenharmony_ci
38433d722a9Sopenharmony_ci<br>
38533d722a9Sopenharmony_ci
38633d722a9Sopenharmony_ci
38733d722a9Sopenharmony_ci## 内置类型
38833d722a9Sopenharmony_ci
38933d722a9Sopenharmony_ci除了所有的原生类型(i32 &lt;=&gt; int32_t)之外,还有以下常见类型可用于共享结构的字段以及函数的参数和返回值。
39033d722a9Sopenharmony_ci
39133d722a9Sopenharmony_ci<table>
39233d722a9Sopenharmony_ci<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
39333d722a9Sopenharmony_ci<tr><td>String</td><td>rust::String</td><td></td></tr>
39433d722a9Sopenharmony_ci<tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
39533d722a9Sopenharmony_ci<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
39633d722a9Sopenharmony_ci<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
39733d722a9Sopenharmony_ci<tr><td><a href="https://docs.rs/cxx/1.0/CXX/struct.CXXString.html">CXXString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
39833d722a9Sopenharmony_ci<tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
39933d722a9Sopenharmony_ci<tr><td><a href="https://docs.rs/cxx/1.0/CXX/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
40033d722a9Sopenharmony_ci<tr><td><a href="https://docs.rs/cxx/1.0/CXX/struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
40133d722a9Sopenharmony_ci<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
40233d722a9Sopenharmony_ci<tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
40333d722a9Sopenharmony_ci<tr><td><a href="https://docs.rs/cxx/1.0/CXX/struct.CXXVector.html">CXXVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
40433d722a9Sopenharmony_ci<tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
40533d722a9Sopenharmony_ci<tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
40633d722a9Sopenharmony_ci<tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
40733d722a9Sopenharmony_ci</table>
40833d722a9Sopenharmony_ci
40933d722a9Sopenharmony_ci`rust`命名空间的C++ API是由*include/CXX.h*文件定义的。使用这些类型时种类的时候,需要C++代码中包含这个头文件。
41033d722a9Sopenharmony_ci
41133d722a9Sopenharmony_ci以下类型很快被支持,只是还没有实现。
41233d722a9Sopenharmony_ci
41333d722a9Sopenharmony_ci<table>
41433d722a9Sopenharmony_ci<tr><th>name in Rust</th><th>name in C++</th></tr>
41533d722a9Sopenharmony_ci<tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
41633d722a9Sopenharmony_ci<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
41733d722a9Sopenharmony_ci<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
41833d722a9Sopenharmony_ci<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
41933d722a9Sopenharmony_ci<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
42033d722a9Sopenharmony_ci<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
42133d722a9Sopenharmony_ci</table>
42233d722a9Sopenharmony_ci
42333d722a9Sopenharmony_ci<br>
42433d722a9Sopenharmony_ci
42533d722a9Sopenharmony_ci## 开发者贡献
42633d722a9Sopenharmony_ci
42733d722a9Sopenharmony_ci当前CXX工具还没有达到普遍使用阶段,在使用该工具的过程中有任何问题欢迎开发者在社区issue中反馈。
42833d722a9Sopenharmony_ci
42933d722a9Sopenharmony_ci<br>
430