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;
}
}
- 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óduloffi
(embora isso não se aplique a projetos Android). - Para visualizar o código C++ gerado, procure em
target/cxxbridge
.