Обёртка для abs(3)
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn abs(x: i32) -> i32;
fn main() {
let x = -42;
let abs_x = abs(x);
println!("{x}, {abs_x}");
}
На этом слайде мы задаём шаблон написания обёрток.
Найдите внешнее определение сигнатуры функции. Напишите соответствующую функцию на Rust внутри блока extern. Выясните, какие инварианты безопасности нужно соблюдать. Решите, можно ли пометить функцию как безопасную.
Обратите внимание, что пока это не работает.
Добавьте блок extern:
#![allow(unused)]
fn main() {
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
unsafe extern "C" {
fn abs(x: i32) -> i32;
}
}
Объясните, что многие функции POSIX доступны в Rust, потому что Cargo по умолчанию линкуется со стандартной библиотекой C (libc), которая вводит её символы в область видимости программы.
Покажите man 3 abs в терминале или страницу в вебе.
Объясните, что наша сигнатура функции должна совпадать с её определением: int abs(int j);.
Обновите блок кода, чтобы использовать типы C.
#![allow(unused)]
fn main() {
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::c_int;
unsafe extern "C" {
fn abs(x: c_int) -> c_int;
}
}
Обсудите обоснование: использование ffi::c_int повышает переносимость кода. Когда стандартная библиотека собирается под целевую платформу, платформа может определить разрядность. Согласно стандарту C, c_int может быть определён как i16, а не как гораздо более распространённый i32.
(По желанию) Покажите документацию для c_int, чтобы показать, что это псевдоним типа для i32.
Попробуйте скомпилировать, чтобы получить сообщение «error: extern blocks must be unsafe».
Добавьте ключевое слово unsafe к блоку:
#![allow(unused)]
fn main() {
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::c_int;
unsafe extern "C" {
fn abs(x: c_int) -> c_int;
}
}
Убедитесь, что слушатели понимают значение этого изменения. Теперь мы обязаны соблюдать типобезопасность и другие предусловия безопасности.
Скомпилируйте снова.
Добавьте ключевое слово safe к функции abs:
#![allow(unused)]
fn main() {
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::c_int;
unsafe extern "C" {
safe fn abs(x: c_int) -> c_int;
}
}
Объясните, что safe fn помечает abs как безопасную для вызова без блока unsafe.
Готовая программа для справки:
// Copyright 2026 Google LLC
// SPDX-License-Identifier: Apache-2.0
use std::ffi::c_int;
unsafe extern "C" {
safe fn abs(x: c_int) -> c_int;
}
fn main() {
let x = -42;
let abs_x = abs(x);
println!("{x}, {abs_x}");
}