plugin_interfaces/
callbacks.rs

1use std::collections::HashMap;
2use std::ffi::c_char;
3use std::sync::{Arc, Mutex, OnceLock};
4
5/// 主程序提供给插件的回调函数集合
6/// 这些函数指针在插件加载时由主程序传递给插件
7#[repr(C)]
8#[derive(Clone)]
9pub struct HostCallbacks {
10    /// 向前端发送消息
11    pub send_to_frontend: extern "C" fn(*const c_char, *const c_char) -> bool,
12
13    /// 获取应用配置
14    pub get_app_config: extern "C" fn(*const c_char) -> *const c_char,
15
16    /// 调用其他插件
17    pub call_other_plugin: extern "C" fn(*const c_char, *const c_char) -> *const c_char,
18}
19
20impl std::fmt::Debug for HostCallbacks {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        f.debug_struct("HostCallbacks")
23            .field("send_to_frontend", &"<function pointer>")
24            .field("get_app_config", &"<function pointer>")
25            .field("call_other_plugin", &"<function pointer>")
26            .finish()
27    }
28}
29
30/// 实例级别的回调函数存储
31/// 每个插件实例都有自己独立的回调函数集合
32static INSTANCE_CALLBACKS: OnceLock<Arc<Mutex<HashMap<String, HostCallbacks>>>> = OnceLock::new();
33
34/// 初始化实例回调函数存储
35fn init_instance_callbacks() -> &'static Arc<Mutex<HashMap<String, HostCallbacks>>> {
36    INSTANCE_CALLBACKS.get_or_init(|| Arc::new(Mutex::new(HashMap::new())))
37}
38
39/// 设置指定实例的主程序回调函数(由主程序调用)
40pub fn set_host_callbacks(instance_id: &str, callbacks: HostCallbacks) -> Result<(), String> {
41    let storage = init_instance_callbacks();
42    let mut map = storage
43        .lock()
44        .map_err(|_| "Failed to lock callbacks storage")?;
45    map.insert(instance_id.to_string(), callbacks);
46    Ok(())
47}
48
49/// 获取指定实例的主程序回调函数(由插件调用)
50pub fn get_host_callbacks(instance_id: &str) -> Option<HostCallbacks> {
51    let storage = init_instance_callbacks();
52    let map = storage.lock().ok()?;
53    map.get(instance_id).cloned()
54}
55
56/// 清理指定实例的回调函数
57/// 在插件卸载时调用
58pub fn clear_host_callbacks(instance_id: &str) -> bool {
59    let storage = init_instance_callbacks();
60    if let Ok(mut map) = storage.lock() {
61        map.remove(instance_id).is_some()
62    } else {
63        false
64    }
65}