1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Hot-reload mechanics for truce: dylib loading, ABI canary,
//! vtable probe, and the shells (`HotShell<P, S>`, `StaticShell<P, L, S>`)
//! that bridge the user-facing `truce_plugin::PluginLogic` /
//! `truce_plugin::PluginLogic64` leaf traits onto
//! [`truce_core::PluginRuntime`] for format wrappers.
//!
//! Plugin authors don't reach into this crate directly. They write
//! `impl PluginLogic for MyPlugin` (the leaf trait is sample-pinned
//! via the prelude re-export) and the `truce::plugin!` macro picks
//! the static or hot shell based on the `shell` Cargo feature.
//!
//! # ABI boundary
//!
//! Across the dylib boundary the shell holds a
//! `Box<dyn truce_plugin::PluginLogicCore<S>>` - the generic
//! wrapper-facing trait that both leaf traits forward into via
//! blanket impls in `truce-plugin`. The single trait object
//! carries DSP and GUI methods through one vtable, with `S` baked
//! in by the shell's generic parameter (and recorded in
//! `AbiCanary::sample_precision` so a precision mismatch fails
//! the canary check before vtable-binding).
//!
//! ```ignore
//! use truce_loader::{AbiCanary, PluginLogic, PluginLogicCore};
//!
//! struct MyPlugin { /* ... */ }
//! impl PluginLogic for MyPlugin { /* DSP + GUI */ }
//!
//! // Emitted by `truce::plugin!`; plugin authors don't write these
//! // by hand. `Sample` resolves through the prelude alias
//! // (`f32` for `prelude` / `prelude32` / `prelude64m`,
//! // `f64` for `prelude64`). The macro also emits a
//! // `truce_vtable_probe` symbol that constructs an internal
//! // `ProbePlugin`; that type lives in `__macro_deps` and isn't
//! // intended for direct use.
//! #[unsafe(no_mangle)]
//! pub fn truce_create(p: *const ()) -> Box<dyn PluginLogicCore<Sample>> {
//! Box::new(MyPlugin::new(/* params from p */))
//! }
//!
//! #[unsafe(no_mangle)]
//! pub fn truce_abi_canary() -> AbiCanary { AbiCanary::current::<Sample>() }
//! ```
pub use AbiCanary;
// `ProbePlugin`, `verify_probe`, and `ProbeError` are loader-internal.
// `ProbePlugin` lives under `__macro_deps` so the `export_plugin!`
// macro's `truce_vtable_probe` body can name it without leaking the
// type at the crate root. `verify_probe` / `ProbeError` are only used
// by `NativeLoader::build_candidate` (gated on `feature = "shell"`)
// and are reached via `crate::canary` directly inside `loader.rs`.
// Format wrappers and plugin authors reach the probe by dlopening
// the `truce_vtable_probe` symbol the macro emits, not by `use` import.
pub use *;
// Source the leaf + core traits directly from `truce-plugin` rather
// than via the optional `truce-gui` re-export, so these names are
// reachable regardless of whether the `builtin-gui` feature is on.
pub use ;
pub use NativeLoader;
/// Export the `#[unsafe(no_mangle)]` functions required by the shell.
///
/// `params_ptr` is a raw `Arc<Params>` pointer from the shell.
/// The plugin receives shared params - one copy, no sync.