rust-ffi-safe-wrappers について
外部インターフェースを安全にラップする Rust 開発者向けスキルです。生のバインディングを unsafe 境界に分離し、Rust API の所有権、エラー、後処理、パニック動作を明確にします。
主な機能
- 01生のバインディングと安全なラッパーを分離
- 02ABI と所有権の契約を確認
- 03C 互換のデータ配置を定義
- 04C 文字列とハンドルを管理
- 05外部エラーを Result に変換
- 06パニックとコールバックの動作を定義
活用シーン
- 01C ライブラリ向け Rust バインディングのレビュー
- 02外部ハンドルに後処理を備えたラッパーを作成
- 03文字列とバッファーの所有権を確認
- 04Rust 2024 の FFI 宣言を監査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ lvtd-llc/ skills --skill rust-ffi-safe-wrappersインストール後、Claude Code で/rust-ffi-safe-wrappersを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlreferences/ffi-boundary-patterns.md
詳細
Rust FFI セーフラッパー
所有権、ライフタイム、エラー、クリーンアップを明確にする Rust API で、外部インターフェースをラップする際にこのスキルを使用します。FFI コードは生の境界では unsafe とし、通常の Rust 呼び出し元には安全に使えるようにします。
基本的なワークフロー
- 生の宣言とセーフラッパーを分離します。生の
unsafe externバインディングは、小さな非公開モジュールに配置します。 - 外部ヘッダーまたはドキュメントを参照して、ABI、型のレイアウト、呼び出し規約、所有権、null 許容性、スレッド処理、エラー規約を確認します。
- モダンな Rust、特に Rust 2024 エディションのコードでは、
unsafe extern "C"ブロックを使用します。安全性が条件に左右される項目は修飾しないか、明示的にunsafeとし、すべての Rust 入力に対して呼び出しが安全な場合に限り、個々の extern 項目にsafeを付けます。 - ABI 境界を越える構造体と列挙型には
#[repr(C)]を使用します。Rust 専用のレイアウト型を C に公開しないでください。 - C に渡す所有 NUL 終端文字列には
CStringを、借用する C 文字列にはCStrを使用します。任意の C メモリを Rust 所有のものとして扱わないでください。 - 生のハンドルは、非公開フィールドと、対応する外部デアロケーターを使った
Dropクリーンアップを備える Rust 型でラップします。 - Rust のパニックが
extern "C"境界を越えないようにします。意図的に"C-unwind"を使用する場合に限り、パニックを捕捉するか、アンワインドを許可する ABI を公開します。
ラッパーのルール
FFI バインディングを追加またはレビューする前に、references/ffi-boundary-patterns.md を読んでください。
- 整数サイズを推測する代わりに、
core::ffiまたはstd::ffiの C 型を優先します。 - 外部エラーコードは、ラッパー境界で Rust の
Resultに変換します。 - 役立つ場合は、null 許容ハンドルを内部で
Option<NonNull<T>>として表し、呼び出し元には安全な Rust 型を公開します。 - コンパイラーが関係を認識できない場合は、通常の参照または
PhantomDataを使って、借用値のライフタイムを所有者に結び付けます。 - 外部ライブラリでプロセス全体のセットアップが必要な場合は、
OnceLock、LazyLock、またはOnceを使って、初期化とシャットダウンを冪等にします。 - 大規模または変更頻度の高い C ヘッダーには
bindgenを、Rust API を C に公開する場合にはcbindgenを使用します。ただし、生成された unsafe シグネチャも必ずレビューしてください。
Rust 2024 の構文チェック
unsafe extern "C" {
pub fn library_open(path: *const core::ffi::c_char) -> *mut RawHandle;
pub fn library_close(handle: *mut RawHandle);
// Mark an item `safe` only when calling it is valid for all Rust inputs:
// pub safe fn library_version() -> core::ffi::c_int;
}
// SAFETY: This exported symbol name is unique for this library.
#[unsafe(no_mangle)]
pub extern "C" fn plugin_version() -> core::ffi::c_int {
1
}
no_mangle、export_name、link_section などの unsafe 属性は、Rust 2024 エディションのコードでは unsafe(...) 形式が必要です。シンボルの一意性やリンカーの動作が契約の一部である場合は、SAFETY コメントを記載します。
レビューチェックリスト
- 生のバインディングは非公開にするか、セーフラッパーと明確に分離します。
- すべてのポインターパラメーターについて、null 許容性と所有権の規則を文書化します。
- すべての割り当ては、同じ側、または明示的に対応付けられたデアロケーターによって解放されます。
- 文字列とバッファーについて、長さ、エンコーディング、NUL バイト要件を維持します。
- 境界を越えるパニック、コールバック、スレッドの動作を明確に定めます。
コメント
Markdown 対応