use std::path::Path;
use crate::{MirPlugin, PluginDeclaration, MIR_PLUGIN_API_VERSION};
#[derive(Debug, thiserror::Error)]
pub enum DylibError {
#[error("cannot load plugin library {path}: {source}")]
Load {
path: String,
source: libloading::Error,
},
#[error("{path} exports no MIR_PLUGIN_DECLARATION symbol — not a mir plugin (did you use mir_plugin::export_plugin!?)")]
MissingDeclaration { path: String },
#[error("{path} was built against mir plugin API v{found}, this binary requires v{expected}")]
ApiVersionMismatch {
path: String,
found: u32,
expected: u32,
},
}
pub fn load(path: &Path) -> Result<Box<dyn MirPlugin>, DylibError> {
let display = path.display().to_string();
let lib = unsafe { libloading::Library::new(path) }.map_err(|source| DylibError::Load {
path: display.clone(),
source,
})?;
let decl = unsafe { lib.get::<*const PluginDeclaration>(b"MIR_PLUGIN_DECLARATION\0") }
.map_err(|_| DylibError::MissingDeclaration {
path: display.clone(),
})?;
let decl: &PluginDeclaration = unsafe { &**decl };
if decl.api_version != MIR_PLUGIN_API_VERSION {
return Err(DylibError::ApiVersionMismatch {
path: display,
found: decl.api_version,
expected: MIR_PLUGIN_API_VERSION,
});
}
let plugin = (decl.create)();
std::mem::forget(lib);
Ok(plugin)
}