use std::ffi::CStr;
use std::os::raw::c_char;
pub struct PluginManager;
impl PluginManager {
pub fn log(msg: &str) {
eprintln!("[PluMA/Rust] {}", msg);
}
pub fn dependency(plugin: &str) {
Self::log(&format!("Checking dependency: {}", plugin));
}
pub fn prefix() -> String {
std::env::var("PLUMA_PREFIX").unwrap_or_else(|_| String::from(""))
}
pub fn add_prefix(filename: &str) -> String {
format!("{}/{}", Self::prefix(), filename)
}
}
pub unsafe fn c_str_to_string(ptr: *const c_char) -> String {
if ptr.is_null() {
return String::new();
}
CStr::from_ptr(ptr)
.to_str()
.unwrap_or("")
.to_string()
}
#[macro_export]
macro_rules! pluma_export_plugin {
($plugin_type:ty) => {
#[no_mangle]
pub extern "C" fn plugin_create() -> *mut std::ffi::c_void {
let plugin = Box::new(<$plugin_type as pluma_plugin_trait::PlumaPlugin>::new());
Box::into_raw(plugin) as *mut std::ffi::c_void
}
#[no_mangle]
pub extern "C" fn plugin_destroy(ptr: *mut std::ffi::c_void) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr as *mut $plugin_type);
}
}
}
#[no_mangle]
pub extern "C" fn plugin_input(ptr: *mut std::ffi::c_void, filename: *const std::os::raw::c_char) {
if ptr.is_null() || filename.is_null() {
return;
}
unsafe {
let plugin = &mut *(ptr as *mut $plugin_type);
let filename_str = std::ffi::CStr::from_ptr(filename)
.to_str()
.unwrap_or("");
plugin.input(filename_str);
}
}
#[no_mangle]
pub extern "C" fn plugin_run(ptr: *mut std::ffi::c_void) {
if ptr.is_null() {
return;
}
unsafe {
let plugin = &mut *(ptr as *mut $plugin_type);
plugin.run();
}
}
#[no_mangle]
pub extern "C" fn plugin_output(ptr: *mut std::ffi::c_void, filename: *const std::os::raw::c_char) {
if ptr.is_null() || filename.is_null() {
return;
}
unsafe {
let plugin = &mut *(ptr as *mut $plugin_type);
let filename_str = std::ffi::CStr::from_ptr(filename)
.to_str()
.unwrap_or("");
plugin.output(filename_str);
}
}
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_c_str_conversion() {
let test_str = std::ffi::CString::new("test").unwrap();
unsafe {
let result = c_str_to_string(test_str.as_ptr());
assert_eq!(result, "test");
}
}
#[test]
fn test_null_c_str() {
unsafe {
let result = c_str_to_string(std::ptr::null());
assert_eq!(result, "");
}
}
}