From 8cffa11669290acc583009fd25ec64578d29ad03 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 29 Aug 2025 00:57:16 +0200 Subject: [PATCH] Better plugin loader --- src/lib.rs | 17 +++++++------- src/loader.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 26 +++++++-------------- 3 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 src/loader.rs diff --git a/src/lib.rs b/src/lib.rs index 5d6cb01..0ed26cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,20 @@ -pub trait Plugin { +pub mod loader; + +pub trait PluginApi { fn init(&mut self); } #[macro_export] macro_rules! export_plugin { ($plugin_type:ty) => { - static mut PLUGIN: Option<$plugin_type> = None; + static PLUGIN: std::sync::Mutex> = std::sync::Mutex::new(None); - #[no_mangle] + #[unsafe(no_mangle)] pub extern "C" fn init() { - unsafe { - PLUGIN = Some(<$plugin_type>::default()); - if let Some(plugin) = PLUGIN.as_mut() { - plugin.init(); - } + let mut plugin = PLUGIN.lock().unwrap(); + *plugin = Some(<$plugin_type>::default()); + if let Some(plugin) = plugin.as_mut() { + plugin.init(); } } }; diff --git a/src/loader.rs b/src/loader.rs new file mode 100644 index 0000000..1fb7637 --- /dev/null +++ b/src/loader.rs @@ -0,0 +1,63 @@ +use std::path::Path; + +use wasmtime::*; +use wasmtime_wasi::{WasiCtxBuilder, preview1::WasiP1Ctx}; + +use crate::PluginApi; + +pub enum PluginInstance { + Wasm(Instance, Store), + StatiC(Box), +} + +pub fn load_plugin(wasm_path: &str) -> anyhow::Result { + let engine = Engine::default(); + let mut store = Store::new( + &engine, + WasiCtxBuilder::new() + .inherit_stdout() + .inherit_stderr() + .build_p1(), + ); + let module = Module::from_file(&engine, wasm_path)?; + let mut linker = Linker::new(&engine); + + wasmtime_wasi::preview1::add_to_linker_sync(&mut linker, |s| s)?; + + let instance = linker.instantiate(&mut store, &module)?; + Ok(PluginInstance::Wasm(instance, store)) +} + +pub fn load_plugins(arr: &mut Vec, path: &Path) { + if path.is_dir() { + for entry in std::fs::read_dir(path).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.extension().and_then(|s| s.to_str()) == Some("wasm") { + println!("Loading plugin: {:?}", path); + match load_plugin(path.to_str().unwrap()) { + Ok(plugin) => { + arr.push(plugin); + } + Err(e) => eprintln!("Failed to load plugin {:?}: {}", path, e), + } + } + } + } else { + eprintln!("{:?} is not a directory", path); + } +} + +impl PluginApi for PluginInstance { + fn init(&mut self) { + match self { + PluginInstance::Wasm(instance, store) => { + let init = instance + .get_typed_func::<(), ()>(&mut *store, "init") + .unwrap(); + init.call(store, ()).unwrap(); + } + PluginInstance::StatiC(plugin) => plugin.init(), + } + } +} diff --git a/src/main.rs b/src/main.rs index 79f3221..211d06c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,12 @@ -use wasmtime::*; -use wasmtime_wasi::WasiCtxBuilder; - -fn load_plugin(wasm_path: &str) -> anyhow::Result<()> { - let engine = Engine::default(); - let mut store = Store::new(&engine, WasiCtxBuilder::new().inherit_stdout().inherit_stderr().build_p1()); - let module = Module::from_file(&engine, wasm_path)?; - let mut linker = Linker::new(&engine); - - wasmtime_wasi::preview1::add_to_linker_sync(&mut linker, |s| s)?; - - let instance = linker.instantiate(&mut store, &module)?; - let init = instance.get_typed_func::<(), ()>(&mut store, "init")?; - init.call(&mut store, ())?; - - Ok(()) -} +use voxa_server::PluginApi; fn main() -> anyhow::Result<()> { - load_plugin("plugins/test_plugin.wasm")?; + let mut plugins = Vec::new(); + voxa_server::loader::load_plugins(&mut plugins, std::path::Path::new("./plugins")); + + for plugin in &mut plugins { + plugin.init(); + } + Ok(()) }