원클릭으로
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