Skip to main content

Module abi

Module abi 

Source
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:

  1. 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.

  2. 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 leading ctx argument — 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:

TierTypeOwnershipFree function
StatelessAbiTable<T>none (static vtable)
Instance (multi-owner)AbiRef<T>ref-counted via retain/release fn ptrs in AbiStableDynRefprovided by the plugin
Data (single-owner)AbiBox / AbiBoxHandlemove-only, exactly one ownerfree fn ptr in the box, provided by the allocating module

Cross-module safety rules enforced by construction:

  1. Allocator symmetryfree/release always execute inside the module that allocated (the function pointer belongs to that module’s code, e.g. AbiBox::from_vec pairs with a Rust-plugin allocator).
  2. Library lifetimeAbiBoxHandle and AbiRef<T> own a DynLib (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.
AbiBoxHandle
Host-side owning handle over a AbiBox received from a foreign module.
AbiRef
Ref-counted handle to a foreign plugin object exposed through a *_get_dyn style entry point returning an AbiStableDynRef.
AbiTable
Load a Copy-sized vtable/descriptor struct from a dynamic library.
GeneratedFunction
Descriptor for a generated math function (matches C++ GeneratedFunction)
MathModuleVtable
Vtable struct matching C++ MathModuleVtable layout exactly

Functions§

abi_box_free_rust
Rust plugin free function paired with AbiBox::from_vec.

Type Aliases§

MathSession
Opaque handle for a C++ MathSession