O Módulo Bridge

O CXX depende de uma descrição das assinaturas de função que serão expostas de cada linguagem para a outra. Você fornece essa descrição usando blocos externos em um módulo Rust anotado com a macro de atributo #[cxx::bridge].

#[allow(unsafe_op_in_unsafe_fn)] #[cxx::bridge(namespace = "org::blobstore")] mod ffi { // Estruturas compartilhadas com campos visíveis para ambas as linguagens. struct BlobMetadata { size: usize, tags: Vec<String>, } // Tipos e assinaturas Rust expostos ao C++. extern "Rust" { type MultiBuf; fn next_chunk(buf: &mut MultiBuf) -> &[u8]; } // Tipos e assinaturas C++ expostos ao 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; } }

Speaker Notes

  • O bridge geralmente é declarado em um módulo ffi dentro do seu crate.
  • A partir das declarações feitas no módulo bridge, o CXX gerará definições de tipo/função correspondentes em Rust e C++ para expor esses itens para ambas as linguagens.
  • Para visualizar o código Rust gerado, use cargo-expand para visualizar a macro de procedimento expandida. Para a maioria dos exemplos, você usaria cargo expand ::ffi para expandir apenas o módulo ffi (embora isso não se aplique a projetos Android).
  • Para visualizar o código C++ gerado, procure em target/cxxbridge.