一键导入
ffi
Rust FFI Best Practices guidance for Fortress Rollback. Use when Writing FFI code, C interop, bindgen usage.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Rust FFI Best Practices guidance for Fortress Rollback. Use when Writing FFI code, C interop, bindgen usage.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Crate Publishing guidance for Fortress Rollback. Use when Publishing to crates.io, version bumps, release checklist.
Changelog Practices guidance for Fortress Rollback. Use when Writing CHANGELOG entries, deciding what to document.
Design Decision Log Pattern guidance for Fortress Rollback. Use when Architectural decisions, design alternatives, superseding prior choices.
Repository-wide engineering policy and project context for Fortress Rollback. Use when implementing, diagnosing, reviewing, testing, documenting, or releasing changes in this repository.
GitHub Actions Best Practices guidance for Fortress Rollback. Use when Writing GitHub Actions workflows, CI debugging, actionlint, caching.
Workspace Organization guidance for Fortress Rollback. Use when Organizing workspace, splitting crates, module structure decisions.
| name | ffi |
| description | Rust FFI Best Practices guidance for Fortress Rollback. Use when Writing FFI code, C interop, bindgen usage. |
Good candidates: Leaf libraries, parsers, modules processing untrusted data, media handling. Avoid converting: Battle-tested crypto, code without allocation, long-stable code. Problematic: Complex OOP hierarchies, Qt apps, template-heavy code.
| Tool | Direction | Best For |
|---|---|---|
extern "C" | Both | Simple C functions |
bindgen | C/C++ -> Rust | Consuming C libraries |
cbindgen | Rust -> C/C++ | Exposing Rust to C |
CXX | Bidirectional | Safe interop with type restrictions |
AutoCXX | C++ -> Rust | Existing C++ APIs |
UniFFI | Rust -> Many | Mobile (Swift/Kotlin) |
PyO3 | Rust <-> Python | Python extensions |
#[no_mangle]
pub unsafe extern "C" fn process_string(input: *const c_char) -> c_int {
if input.is_null() { return -1; }
let c_str = match CStr::from_ptr(input).to_str() {
Ok(s) => s,
Err(_) => return -2,
};
0 // success
}
pub struct GameEngine { /* fields */ }
#[no_mangle]
pub extern "C" fn engine_create() -> *mut GameEngine {
Box::into_raw(Box::new(GameEngine::new()))
}
#[no_mangle]
pub unsafe extern "C" fn engine_destroy(handle: *mut GameEngine) {
if !handle.is_null() { drop(Box::from_raw(handle)); }
}
Treat the Rust/C++ boundary like a service boundary. Don't share memory; exchange messages.
| Pattern | Rule |
|---|---|
| Rust creates, C borrows | Rust retains ownership; C must not store pointer |
| Rust creates, C takes ownership | C must call Rust's free function |
| C creates, Rust uses | Rust must not free; document lifetime |
| Shared data | Reference counting or explicit sync |
#[repr(C)]
pub enum ErrorCode {
Success = 0, NullPointer = -1, InvalidUtf8 = -2,
InvalidArgument = -3, OutOfMemory = -4, Unknown = -255,
}
thread_local! { static LAST_ERROR: RefCell<Option<CString>> = RefCell::new(None); }
#[no_mangle]
pub extern "C" fn get_last_error() -> *const c_char {
LAST_ERROR.with(|e| e.borrow().as_ref().map_or(ptr::null(), |s| s.as_ptr()))
}
#[no_mangle]
pub extern "C" fn safe_function() -> ErrorCode {
// Closure must be UnwindSafe; AssertUnwindSafe opts in when you've verified safety
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { /* logic */ })) {
Ok(result) => result,
Err(_) => ErrorCode::Unknown,
}
}
#[cxx::bridge]
mod ffi {
struct GameConfig { width: u32, height: u32, fullscreen: bool }
extern "Rust" {
type GameEngine;
fn create_engine(config: GameConfig) -> Box<GameEngine>;
}
unsafe extern "C++" {
include!("renderer.h");
type Renderer;
fn render_frame(renderer: &Renderer, data: &[u8]);
}
}
// build.rs: panic is appropriate for build failures
cbindgen::Builder::new()
.with_crate(&crate_dir)
.with_language(cbindgen::Language::C)
.generate().unwrap()
.write_to_file("include/my_lib.h");
// build.rs: panic is appropriate for build failures
bindgen::Builder::default()
.header("wrapper.h")
.generate().unwrap()
.write_to_file(out_path.join("bindings.rs")).unwrap();
[lib]
crate-type = ["cdylib", "staticlib", "lib"]
lto = true in release profile + CC=clangunsafe blocks justified and minimal