# abi-vtable-macro
`#[abi_vtable]` — annotate a Rust trait and get the complete C contract for
[dyn-loader](https://crates.io/crates/dyn-loader)'s **abi mode**:
a `#[repr(C)]` vtable struct, one `extern "C"` thunk per method, a static
vtable instance and a `#[no_mangle]` getter — all generated.
```rust
use abi_vtable_macro::abi_vtable;
#[abi_vtable(name = "calc")]
pub trait Calc {
fn add(&self, a: i32, b: i32) -> i32;
fn is_even(&self, x: i32) -> bool;
}
struct MyCalc;
impl Calc for MyCalc {
fn add(&self, a: i32, b: i32) -> i32 { a + b }
fn is_even(&self, x: i32) -> bool { x % 2 == 0 }
}
// One line: static instance + thunks + vtable + getter.
abi_vtable_impl_calc!(MyCalc, MyCalc);
```
The host (Rust, C, C++, Zig, ...) loads `calc_get_vtable` and calls through
the struct of function pointers — see dyn-loader's `AbiTable`.
## Rules
- Field order of the generated vtable **is** the protocol: it follows trait
method declaration order. Never reorder after release.
- All fn pointers are `extern "C"` (cdecl), ctx-leading (`*mut c_void` first).
- `$instance` must be const-constructible (unit struct, `const fn`, literal).
## License
MIT