Tratamento de Erros no CXX: Exemplo PNG
Um protĂłtipo de um decodificador PNG ilustra o que pode ser feito quando o resultado bem-sucedido nĂŁo pode ser passado pela fronteira FFI:
#[cxx::bridge(namespace = "gfx::rust_bindings")]
mod ffi {
extern "Rust" {
/// Isso retorna um equivalente amigĂĄvel ao FFI de `Result<PngReader<'a>,
/// ()>`.
fn new_png_reader<'a>(input: &'a [u8]) -> Box<ResultOfPngReader<'a>>;
/// _Bindings_ C++ para o tipo `crate::png::ResultOfPngReader`.
type ResultOfPngReader<'a>;
fn is_err(self: &ResultOfPngReader) -> bool;
fn unwrap_as_mut<'a, 'b>(
self: &'b mut ResultOfPngReader<'a>,
) -> &'b mut PngReader<'a>;
/// _Bindings_ C++ para o tipo `crate::png::PngReader`.
type PngReader<'a>;
fn height(self: &PngReader) -> u32;
fn width(self: &PngReader) -> u32;
fn read_rgba8(self: &mut PngReader, output: &mut [u8]) -> bool;
}
}
PngReader
e ResultOfPngReader
são tipos Rust --- objetos desses tipos não podem cruzar a fronteira FFI sem a indireção de um Box<T>
. NĂŁo podemos ter um out_parameter: &mut PngReader
, porque o CXX nĂŁo permite que o C++ armazene objetos Rust por valor.
Este exemplo ilustra que, embora o CXX não suporte genéricos nem modelos arbitrårios, ainda podemos passå-los pela fronteira FFI especializando / monomorfizando-os manualmente em um tipo não genérico. No exemplo, ResultOfPngReader
é um tipo não genérico que encaminha para métodos apropriados de Result<T, E>
(por exemplo, para is_err
, unwrap
e/ou as_mut
).