مدیریت خطا CXX: مثال PNG
نمونه اولیه PNG decoder نشان میدهد که وقتی نتیجه موفقیت آمیز نمیتواند از مرز FFI عبور کند و چه کاری می توان انجام داد:
#[cxx::bridge(namespace = "gfx::rust_bindings")]
mod ffi {
extern "Rust" {
/// This returns an FFI-friendly equivalent of `Result<PngReader<'a>,
/// ()>`.
fn new_png_reader<'a>(input: &'a [u8]) -> Box<ResultOfPngReader<'a>>;
/// C++ bindings for the `crate::png::ResultOfPngReader` type.
type ResultOfPngReader<'a>;
fn is_err(self: &ResultOfPngReader) -> bool;
fn unwrap_as_mut<'a, 'b>(
self: &'b mut ResultOfPngReader<'a>,
) -> &'b mut PngReader<'a>;
/// C++ bindings for the `crate::png::PngReader` type.
type PngReader<'a>;
fn height(self: &PngReader) -> u32;
fn width(self: &PngReader) -> u32;
fn read_rgba8(self: &mut PngReader, output: &mut [u8]) -> bool;
}
}
"PngReader" و "ResultOfPngReader" تایپهای Rust هستند --- objectهای از این نوع نمیتوانند بدون جهتگیری غیرمستقیم Box<T>
از مرز FFI عبور کنند. ما نمیتوانیم out_parameter: &mut PngReader
داشته باشیم، زیرا CXX به ++C اجازه نمیدهد Rust object ها را براساس مقدار ذخیره کند.
این مثال نشان میدهد که حتی اگر CXX از genericها و templateهای دلخواه پشتیبانی نمیکند، ما همچنان میتوانیم آنها را از مرز FFI عبور دهیم و آنها را بهصورت دستی تخصصی/تکشکلی ( specializing / monomorphizing) در یک نوع غیرعمومی تبدیل کنیم. در مثال ResultOfPngReader
یک نوع non-generic است که به متدهای مناسب Result<T, E>
(به عنوان مثال به «is_err»، «unwrap» و/یا «as_mut» ارسال میشود.