Модуль Bridge

CXX покладається на опис сигнатур функцій, які будуть передаватися з однієї мови до іншої. Ви надаєте цей опис за допомогою блоків extern у модулі Rust, анотованому макросом з атрибутом #[cxx::bridge].

#[allow(unsafe_op_in_unsafe_fn)]
#[cxx::bridge(namespace = "org::blobstore")]
mod ffi {
    // Спільні структури з полями, видимими для обох мов.
    struct BlobMetadata {
        size: usize,
        tags: Vec<String>,
    }

    // Типи та сигнатури Rust, що доступні у C++.
    extern "Rust" {
        type MultiBuf;

        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
    }

    // Типи та сигнатури C++, доступні у Rust.
    unsafe extern "C++" {
        include!("include/blobstore.h");

        type BlobstoreClient;

        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
        fn put(self: Pin<&mut BlobstoreClient>, parts: &mut MultiBuf) -> u64;
        fn tag(self: Pin<&mut BlobstoreClient>, blobid: u64, tag: &str);
        fn metadata(&self, blobid: u64) -> BlobMetadata;
    }
}
  • Міст зазвичай оголошується у модулі ffi у вашому крейті.
  • На основі оголошень, зроблених у модулі-містку, CXX згенерує відповідні визначення типів/функцій Rust та C++, щоб зробити ці елементи доступними для обох мов.
  • Щоб переглянути згенерований код Rust, скористайтеся cargo-expand для перегляду розширеного макросу proc. У більшості прикладів ви можете використовувати cargo expand ::ffi для розгортання лише модуля ffi (хоча це не стосується проектів для Android).
  • Щоб переглянути згенерований C++ код, подивіться у target/cxxbridge.