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

Небезопасные внешние функции

Внешние функции для доступа из Rust можно объявить с помощью unsafe extern. Это небезопасно, потому что компилятор не может рассуждать об их поведении. Функции, объявленные в блоке extern, должны быть помечены как safe или unsafe в зависимости от того, есть ли у них предусловия для безопасного использования:

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

use std::ffi::c_char;

unsafe extern "C" {
    // `abs` не работает с указателями и не имеет требований безопасности.
    safe fn abs(input: i32) -> i32;

    /// # Safety
    ///
    /// `s` должен быть указателем на строку C, оканчивающуюся NUL, которая допустима и
    /// не изменяется на протяжении этого вызова функции.
    unsafe fn strlen(s: *const c_char) -> usize;
}

fn main() {
    println!("Absolute value of -3 according to C: {}", abs(-3));

    // SAFETY: Мы передаём указатель на строковый литерал C, который допустим на
    // протяжении всей работы программы.
    unsafe {
        println!("String length: {}", strlen(c"String".as_ptr()));
    }
}
  • Раньше Rust считал все внешние функции небезопасными, но это изменилось в Rust 1.82 с появлением блоков unsafe extern.
  • abs должна быть явно помечена как safe, потому что это внешняя функция (FFI). Вызов внешних функций представляет проблему только тогда, когда эти функции делают что-то с указателями, что может нарушить модель памяти Rust, но в целом любая функция C может иметь неопределённое поведение при любых произвольных обстоятельствах.
  • "C" в этом примере — это ABI; доступны и другие ABI.
  • Обратите внимание, что нет проверки того, что сигнатура функции Rust совпадает с сигнатурой определения функции, — это ответственность разработчика!