super basic rust cdylib plugin system
at master 1.6 kB view raw
1use std::io; 2 3use anyhow::{Context, Result, bail}; 4use libloading::Library; 5use plugin_api::Plugin; 6use tempfile::NamedTempFile; 7 8use crate::LocatedPlugin; 9 10pub struct LoadedPlugin { 11 pub located: LocatedPlugin, 12 pub plugin: Box<dyn Plugin>, 13 // DO NOT MOVE THIS UP! 14 // This is due to rust's dropping order! 15 // If the library gets dropped (unloaded) before the plugin, a segfault will occur. 16 pub lib: Library, 17} 18 19pub fn load(mut plugin: LocatedPlugin) -> Result<LoadedPlugin> { 20 #[cfg(target_os = "linux")] 21 let cdylib = plugin.so; 22 23 #[cfg(target_os = "windows")] 24 let cdylib = plugin.dll; 25 26 #[cfg(target_os = "macos")] 27 let cdylib = plugin.dylib; 28 29 if !cdylib { 30 bail!("unsupported platform"); 31 } 32 33 #[cfg(target_os = "linux")] 34 let cdylib = "plugin.so"; 35 36 #[cfg(target_os = "windows")] 37 let cdylib = "plugin.dll"; 38 39 #[cfg(target_os = "macos")] 40 let cdylib = "plugin.dylib"; 41 42 let mut tmp = NamedTempFile::new().context("failed creating temp file")?; 43 { 44 let mut entry = plugin.zip.by_name(cdylib).unwrap(); 45 io::copy(&mut entry, &mut tmp).context("failed copying cdylib to temp file")?; 46 } 47 48 unsafe { 49 let lib = 50 Library::new(tmp.path().display().to_string()).context("failed loading library")?; 51 let ctor = lib 52 .get::<unsafe extern "Rust" fn() -> Box<dyn Plugin>>(b"provide_plugin") 53 .context("plugin does not have a provide_plugin function")?; 54 let instance = ctor(); 55 56 Ok(LoadedPlugin { 57 located: plugin, 58 lib, 59 plugin: instance, 60 }) 61 } 62}