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.h和lib.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 11433d722a9Sopenharmony_ci 11533d722a9Sopenharmony_ci 11633d722a9Sopenharmony_ci### Rust调用C++ 11733d722a9Sopenharmony_ci 11833d722a9Sopenharmony_ci1. 添加头文件client_blobstore.h。 11933d722a9Sopenharmony_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.cpp。 15033d722a9Sopenharmony_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.h和lib.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 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 <=> 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>&str</td><td>rust::Str</td><td></td></tr> 39533d722a9Sopenharmony_ci<tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> 39633d722a9Sopenharmony_ci<tr><td>&mut [T]</td><td>rust::Slice<T></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<T></td><td>rust::Box<T></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<T></a></td><td>std::unique_ptr<T></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<T></a></td><td>std::shared_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> 40133d722a9Sopenharmony_ci<tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> 40233d722a9Sopenharmony_ci<tr><td>Vec<T></td><td>rust::Vec<T></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<T></a></td><td>std::vector<T></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) -> V</td><td>rust::Fn<V(T, U)></td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr> 40633d722a9Sopenharmony_ci<tr><td>Result<T></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<K, V></td><td><sup><i>tbd</i></sup></td></tr> 41633d722a9Sopenharmony_ci<tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> 41733d722a9Sopenharmony_ci<tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr> 41833d722a9Sopenharmony_ci<tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> 41933d722a9Sopenharmony_ci<tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> 42033d722a9Sopenharmony_ci<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></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