Expand description
§abi — protocol standard layer: C interface tables (ABI-stable)
Load Copy-sized vtable/descriptor structs from dynamic libraries using
plain C function tables — no Rust trait objects, no named-based access,
purely positional dispatch. This is the COM+-like emulated vtable system
(formerly the separate cdyn-loader crate).
Unlike crate::native, this mode is ABI-stable across languages:
the C++ SDK (cdyn-loader-sdks/cpp) and Zig SDK (cdyn-loader-sdks/zig)
build plugins that match these layouts exactly.
§Cross-module memory ownership model
The core of every cross-module boundary is who manages memory, and it reduces to two invariant rules that hold in every mode of this crate:
-
Whoever allocates, deallocates (谁分配谁释放). Memory is never freed across the boundary by the borrower: every pointer crossing the boundary travels paired with a deallocation function pointer that belongs to the module which allocated the memory. Allocators (and CRTs) are not guaranteed to match across module boundaries, so the free must execute inside the allocator’s own module.
-
Whoever creates, operates (谁创建谁操作). Behavior also belongs to the creator: the host receives a calling convention (a
#[repr(C)]vtable layout) plus function pointers, and every operation — method dispatch through thunks, with the instance pointer passed back as the leadingctxargument — executes inside the creator’s module. The host never “has” the object; it only holds pointers and dials the protocol.
Together these mean the only thing that ever crosses a module boundary, in any language, is the protocol itself: a pointer plus function pointers that route both deallocation and operation back to the owning module.
This crate provides three ownership tiers, all following those rules:
| Tier | Type | Ownership | Free function |
|---|---|---|---|
| Stateless | AbiTable<T> | none (static vtable) | — |
| Instance (multi-owner) | AbiRef<T> | ref-counted via retain/release fn ptrs in AbiStableDynRef | provided by the plugin |
| Data (single-owner) | AbiBox / AbiBoxHandle | move-only, exactly one owner | free fn ptr in the box, provided by the allocating module |
Cross-module safety rules enforced by construction:
- Allocator symmetry —
free/releasealways execute inside the module that allocated (the function pointer belongs to that module’s code, e.g.AbiBox::from_vecpairs with a Rust-plugin allocator). - Library lifetime —
AbiBoxHandleandAbiRef<T>own aDynLib(Arc-shared), so the library cannot be unloaded while a handle (and thus a free/release fn ptr) still exists.
§Usage
#[repr(C)]
struct MyVtable {
add: unsafe extern "C" fn(i32, i32) -> i32,
name: unsafe extern "C" fn() -> *const std::ffi::c_char,
}
let plugin = unsafe { AbiTable::<MyVtable>::load("libmy.so", b"my_get_vtable\0")? };
let n = unsafe { (plugin.vtable().add)(1, 2) };Re-exports§
pub use crate::native::ModuleDynEntryPoint;
Structs§
- AbiBox
- A cross-module data box: memory allocated and freed by the same module.
- AbiBox
Handle - Host-side owning handle over a
AbiBoxreceived from a foreign module. - AbiRef
- Ref-counted handle to a foreign plugin object exposed through a
*_get_dynstyle entry point returning anAbiStableDynRef. - AbiTable
- Load a Copy-sized vtable/descriptor struct from a dynamic library.
- Generated
Function - Descriptor for a generated math function (matches C++ GeneratedFunction)
- Math
Module Vtable - Vtable struct matching C++ MathModuleVtable layout exactly
Functions§
- abi_
box_ ⚠free_ rust - Rust plugin free function paired with
AbiBox::from_vec.
Type Aliases§
- Math
Session - Opaque handle for a C++ MathSession