unsafe な外部関数

unsafe extern を使うと、Rust からアクセスするための外部関数を宣言できます。 これは、それらの振る舞いについてコンパイラが推論する手段を持たないため、unsafe です。 extern ブロック内で宣言される関数には、安全に使用するための事前条件があるかどうかに 応じて、safe または unsafe を付ける必要があります:

// 著作権 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` は、有効な NUL 終端 C 文字列へのポインタでなければならず、この関数呼び出しの
    /// 間は変更されてはなりません。
    unsafe fn strlen(s: *const c_char) -> usize;
}

fn main() {
    println!("C による -3 の絶対値: {}", abs(-3));

    unsafe {
        // SAFETY: プログラムの実行中ずっと有効な C 文字列リテラルへのポインタを
        // 渡しています。
        println!("文字列の長さ: {}", strlen(c"String".as_ptr()));
    }
}
  • Rust は以前、すべての extern 関数を unsafe と見なしていましたが、Rust 1.82 で unsafe extern ブロックが導入されてからは変わりました。
  • abs は外部関数 (FFI) であるため、明示的に safe とマークしなければなりません。 外部関数の呼び出しが問題になるのは、それらの関数が Rust のメモリモデルに違反しうる ポインタ操作を行う場合だけですが、一般論としては、どのような C 関数でも 任意の状況で未定義動作を起こしうる可能性があります。
  • この例の "C" は ABI を表しています; 他の ABI も利用できます
  • Rust の関数シグネチャが関数定義のものと一致していることを検証する仕組みは ありません – それを保証するのはあなた自身です!