Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Repository Instructions

Before making changes, read [AI_WORKFLOW.md](AI_WORKFLOW.md) for coding rules,
[PHILOSOPHY.md](PHILOSOPHY.md) for FFI design and ownership requirements, and
[CONTRIBUTING.md](CONTRIBUTING.md) for development and validation guidance.

For FFI changes, follow the macro-first pre-flight checklist in AI_WORKFLOW.md.
Export a library-prefixed C ABI free function that delegates to
`cimpl::cimpl_free`; the Rust function is not itself an exported C ABI symbol.
Do not let panics unwind across the C ABI boundary.

When changing FFI conventions, update AI_WORKFLOW.md and PHILOSOPHY.md together
so the implementation and AI guidance remain consistent.
31 changes: 31 additions & 0 deletions AI_WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,37 @@ pub extern "C" fn vc_to_string(ptr: *mut ValueConverter) -> *mut c_char {

See `examples/reference/` for a complete implementation of this pattern.

## Required FFI Safety and Ownership Rules

### Export a Library-Specific Free Function

**Important:** `cimpl::cimpl_free()` is a Rust function, not an exported
`#[no_mangle]` C ABI function. Each consuming library must export its own
library-prefixed wrapper, as in `examples/reference/src/ffi.rs`:

```rust
use std::ffi::c_void;

#[no_mangle]
pub extern "C" fn vc_free(ptr: *mut c_void) -> i32 {
cimpl::cimpl_free(ptr)
}
```

Use the consuming library's prefix instead of `vc`. Preserve the `i32` return
value. Callers must release cimpl-tracked objects, strings, and byte arrays
through the allocating library's free function, not C `free()` or an untracked
Rust deallocator. The `cimpl_free!` macro does not export a C ABI symbol either.

### Keep Panics Out of the C ABI

Do not use `panic!()`, `unwrap()`, or `expect()` for recoverable failures in
exported FFI functions. Handle errors with the existing cimpl macros, record the
last error, and return the function's documented error value. Panics must not
unwind across the C ABI boundary.

See `PHILOSOPHY.md` for the ownership and error-handling rationale.

## Common Anti-Patterns to AVOID

### DON'T: Manual null checks
Expand Down
Loading