plugin_interfaces/
metadata.rs

1use serde::{Deserialize, Serialize};
2use std::os::raw::c_char;
3
4/// 插件元数据结构
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct PluginMetadata {
7    pub id: String,
8    pub disabled: bool,
9    pub name: String,
10    pub description: String,
11    pub version: String,
12    pub author: Option<String>,
13    pub library_path: Option<String>, // 动态库文件路径
14    pub config_path: String,          // 配置文件路径
15}
16
17/// FFI安全的插件元数据结构
18/// 使用C风格的字符串指针
19#[repr(C)]
20#[derive(Copy, Clone)]
21pub struct PluginMetadataFFI {
22    pub id: *const c_char,
23    pub disabled: bool,
24    pub name: *const c_char,
25    pub description: *const c_char,
26    pub version: *const c_char,
27    pub author: *const c_char, // 如果为null表示None
28    pub library_path: *const c_char, // 如果为null表示None
29    pub config_path: *const c_char,
30}
31
32impl PluginMetadata {
33    /// 转换为FFI安全的结构
34    /// 注意:调用者需要负责释放返回的字符串内存
35    pub fn to_ffi(&self) -> PluginMetadataFFI {
36        use std::ffi::CString;
37
38        let id = CString::new(self.id.clone()).unwrap().into_raw();
39        let name = CString::new(self.name.clone()).unwrap().into_raw();
40        let description = CString::new(self.description.clone()).unwrap().into_raw();
41        let version = CString::new(self.version.clone()).unwrap().into_raw();
42        let config_path = CString::new(self.config_path.clone()).unwrap().into_raw();
43
44        let author = if let Some(ref author) = self.author {
45            CString::new(author.clone()).unwrap().into_raw()
46        } else {
47            std::ptr::null()
48        };
49
50        let library_path = if let Some(ref path) = self.library_path {
51            CString::new(path.clone()).unwrap().into_raw()
52        } else {
53            std::ptr::null()
54        };
55
56        PluginMetadataFFI {
57            id,
58            disabled: self.disabled,
59            name,
60            description,
61            version,
62            author,
63            library_path,
64            config_path,
65        }
66    }
67}
68
69/// 释放FFI元数据结构中的字符串内存
70/// 必须在不再使用PluginMetadataFFI时调用
71pub unsafe fn free_plugin_metadata_ffi(metadata: PluginMetadataFFI) {
72    use std::ffi::CString;
73
74    if !metadata.id.is_null() {
75        let _ = CString::from_raw(metadata.id as *mut c_char);
76    }
77    if !metadata.name.is_null() {
78        let _ = CString::from_raw(metadata.name as *mut c_char);
79    }
80    if !metadata.description.is_null() {
81        let _ = CString::from_raw(metadata.description as *mut c_char);
82    }
83    if !metadata.version.is_null() {
84        let _ = CString::from_raw(metadata.version as *mut c_char);
85    }
86    if !metadata.config_path.is_null() {
87        let _ = CString::from_raw(metadata.config_path as *mut c_char);
88    }
89    if !metadata.author.is_null() {
90        let _ = CString::from_raw(metadata.author as *mut c_char);
91    }
92    if !metadata.library_path.is_null() {
93        let _ = CString::from_raw(metadata.library_path as *mut c_char);
94    }
95}