CXX 錯誤處理:PNG 範例

PNG 解碼器的原型可說明當成功的結果無法跨越 FFI 邊界時,可以執行哪些操作:

#[cxx::bridge(namespace = "gfx::rust_bindings")]
mod ffi {
    extern "Rust" {
        /// 這回傳一個 FFI 友好的型別,等同於 `Result<PngReader<'a>, ()>`.
        fn new_png_reader<'a>(input: &'a [u8]) -> Box<ResultOfPngReader<'a>>;

        /// `crate::png::ResultOfPngReader` 型別的 C++ 繫結:
        type ResultOfPngReader<'a>;
        fn is_err(self: &ResultOfPngReader) -> bool;
        fn unwrap_as_mut<'a, 'b>(
            self: &'b mut ResultOfPngReader<'a>,
        ) -> &'b mut PngReader<'a>;

        /// `crate::png::PngReader` 型別的 C++ 繫結:
        type PngReader<'a>;
        fn height(self: &PngReader) -> u32;
        fn width(self: &PngReader) -> u32;
        fn read_rgba8(self: &mut PngReader, output: &mut [u8]) -> bool;
    }
}

PngReaderResultOfPngReader 是 Rust 型別,這些型別的物件必須採用 Box<T> 的間接機制,才能跨越 FFI 邊界。我們無法使用 out_parameter: &mut PngReader,因為 CXX 不允許 C++ 依據值儲存 Rust 物件。

本範例說明即使 CXX 不支援任意泛型和範本,我們還是可以手動將這些範本特化/單型化為非泛型型別,傳遞到 FFI 邊界。在範例中,ResultOfPngReader 屬於非泛型型別,會轉送至適當的 Result<T, E> 方法,例如 is_errunwrap 和/或 as_mut