feat(plugin): load external cdylib plugins at runtime (phase 2)
Move BuiltinPlugin into ocs_plugin_api (host feature) so out-of-tree crates can implement it, and add export_plugin! to emit the two C symbols a cdylib exposes: ocs_plugin_api_version (checked first, so an ABI-incompatible build never runs) and ocs_plugin_register -> boxed BuiltinPlugin. The host loads every compatible package from the plugins folder at startup via libloading (desktop only), keeps the library resident for the session, and merges its ribbon tab + command dispatch into the same paths as built-ins (honouring enable/disable). The Plugin Manager shows external packages with a Loaded / incompatible status. Approach B: the plugin hands back a boxed trait object, assuming a matching toolchain + ocs_plugin_api version (the version symbol enforces the latter). crates/ocs_example_plugin is the reference cdylib. Part of the #100 extensibility epic (phase 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
f6219a9609
commit
29c71be101
14 changed files with 402 additions and 36 deletions
|
|
@ -298,8 +298,11 @@ pub(super) struct OpenCADStudio {
|
|||
/// dispatch. Persisted via [`settings::UserSettings::disabled_plugins`].
|
||||
disabled_plugins: rustc_hash::FxHashSet<String>,
|
||||
/// External add-on packages found in the plugins folder, refreshed when the
|
||||
/// Plugin Manager opens. Discovery only — not yet loaded (phase 2).
|
||||
/// Plugin Manager opens.
|
||||
external_plugins: Vec<crate::plugin::external::ExternalPlugin>,
|
||||
/// Ids of external packages actually loaded this session (a subset of
|
||||
/// `external_plugins` — compatible, with a library, dlopen'd at startup).
|
||||
loaded_plugin_ids: rustc_hash::FxHashSet<String>,
|
||||
/// PDSIZE text buffer for the Point Style (DDPTYPE) dialog.
|
||||
point_size_buf: String,
|
||||
/// Point Style size mode: `true` = relative to screen, `false` = absolute.
|
||||
|
|
@ -1465,6 +1468,7 @@ impl OpenCADStudio {
|
|||
modal_dragging: false,
|
||||
disabled_plugins: rustc_hash::FxHashSet::default(),
|
||||
external_plugins: Vec::new(),
|
||||
loaded_plugin_ids: rustc_hash::FxHashSet::default(),
|
||||
point_size_buf: String::new(),
|
||||
point_size_relative: true,
|
||||
default_assoc_prompted: false,
|
||||
|
|
@ -1644,6 +1648,20 @@ impl OpenCADStudio {
|
|||
if let Some(s) = settings::UserSettings::load() {
|
||||
app.apply_settings(&s);
|
||||
}
|
||||
// Load external plugin packages from the plugins folder once, then fold
|
||||
// their ribbon tabs into the ribbon. Skipped under test/wasm.
|
||||
#[cfg(all(not(target_arch = "wasm32"), not(test)))]
|
||||
{
|
||||
for (id, res) in crate::plugin::external::load_at_startup() {
|
||||
if let Err(e) = res {
|
||||
app.command_line
|
||||
.push_error(&format!("Plugin '{id}' failed to load: {e}"));
|
||||
}
|
||||
}
|
||||
app.loaded_plugin_ids =
|
||||
crate::plugin::external::loaded_ids().into_iter().collect();
|
||||
app.rebuild_ribbon_modules();
|
||||
}
|
||||
app.last_saved_settings = Some(app.current_settings());
|
||||
app.sync_ribbon_layers();
|
||||
app
|
||||
|
|
|
|||
Loading…
Reference in a new issue