Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Обработка ошибок 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>>;

        /// Привязки C++ для типа `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>;

        /// Привязки C++ для типа `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 и ResultOfPngReader — типы Rust: объекты этих типов не могут пересекать границу FFI без косвенности через Box<T>. Мы не можем иметь out_parameter: &mut PngReader, потому что CXX не позволяет C++ хранить объекты Rust по значению.

Этот пример показывает, что хотя CXX не поддерживает произвольные обобщения и шаблоны, их всё равно можно передать через границу FFI, вручную специализировав (мономорфизировав) их в необобщённый тип. В примере ResultOfPngReader — необобщённый тип, который перенаправляет вызовы подходящим методам Result<T, E> (например, is_err, unwrap и/или as_mut).