CXX エラーハンドリング: PNG の例

PNG デコーダーのプロトタイプは、成功結果を FFI 境界を越えて渡せない場合に何ができるかを示しています。

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[cxx::bridge(namespace = "gfx::rust_bindings")]
mod ffi {
    extern "Rust" {
        /// これは `Result<PngReader<'a>,
        /// ()>` と FFI フレンドリーに等価なものを返します。
        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)に処理を転送します。