このページの目次
C ABI と bindgen
Rust から C を呼び出す第一步は、型レイアウトを一致させることです。
repr(C)は Rust の struct が C ABI に従ってフィールドを配置し、C ヘッダ内の構造体とバイト単位でアラインメントされることを強制します。bindgen は C ヘッダから対応する Rust 型と関数シグネチャを自動生成し、手動で Rust/C の型マッピングを維持する退屈さとエラーを自動化します。callback の安全性の核心は、C から Rust へのコールバック時に panic が FFI 境界を越えて unwind してはならないという点にあります。
C ↔ Rust 型マッピング
FFI における型の対応は自動的ではありません。std::os::raw または libc クレート内の C 互換型を明示的に使用する必要があります。
| C 型 | Rust 型 (libc) | 注意 |
|---|---|---|
int | c_int (i32) | |
long | c_long | Windows では 32-bit、Linux では 64-bit! |
size_t | usize | |
char * (文字列) | *const c_char → CStr::from_ptr() | |
void * | *mut c_void | |
| 構造体ポインタ (opaque) | *mut MyStruct | 間接参照せず、渡すのみ |
| enum | #[repr(C)] enum | C の enum は c_int サイズ |
重要な罠:long のサイズは LLP64 (Windows) では 4 バイト、LP64 (Linux) では 8 バイトです。C コードが long を 8 バイトとして依存している場合、Windows では i64 を代わりに使用してください。
bindgen による自動化
bindgen は C ヘッダから Rust の外部関数宣言、構造体、定数を自動生成します。
// build.rs
// src/lib.rs
include!;
bindgen が処理すること:基本型のマッピング、struct のアラインメント、ネストされた struct、関数ポインタ、条件付き定義。 処理できないこと:インライン関数 (Rust へ手動でポートが必要)、C++ テンプレート。
Callback: C から Rust への安全な境界
extern "C"
unsafe
callback 内で panic が FFI 境界を越えて発生すると未定義動作 (UB) になります。Cargo.toml で panic = "abort" を設定することは、このリスクを回避する最も直接的な方法です。unwinding を維持する必要がある場合は、callback 内のすべてのロジックを catch_unwind でラップしてください。
参考
- bindgen: rust-lang.github.io/rust-bindgen
- Rustonomicon: FFI
- libc crate: docs.rs/libc
Keywords: C ABI, bindgen, c_int, c_long, c_void, callback, panic across FFI, #[repr(C)]