plugin_interfaces/
symbols.rs

1use crate::metadata::PluginMetadataFFI;
2use crate::callbacks::HostCallbacks;
3use std::os::raw::c_char;
4
5/// FFI安全的插件接口
6/// 使用C风格的函数指针而不是trait对象
7#[repr(C)]
8pub struct PluginInterface {
9    pub plugin_ptr: *mut std::ffi::c_void,
10    pub initialize: unsafe extern "C" fn(*mut std::ffi::c_void, HostCallbacks) -> i32,
11    pub update_ui: unsafe extern "C" fn(*mut std::ffi::c_void, *const std::ffi::c_void, *mut std::ffi::c_void) -> i32,
12    pub on_mount: unsafe extern "C" fn(*mut std::ffi::c_void, PluginMetadataFFI) -> i32,
13    pub on_dispose: unsafe extern "C" fn(*mut std::ffi::c_void) -> i32,
14    pub on_connect: unsafe extern "C" fn(*mut std::ffi::c_void) -> i32,
15    pub on_disconnect: unsafe extern "C" fn(*mut std::ffi::c_void) -> i32,
16    pub handle_message: unsafe extern "C" fn(*mut std::ffi::c_void, *const c_char, *mut *mut c_char) -> i32,
17    pub get_metadata: unsafe extern "C" fn(*mut std::ffi::c_void) -> PluginMetadataFFI,
18    pub destroy: unsafe extern "C" fn(*mut std::ffi::c_void),
19}
20
21/// 插件创建函数类型
22/// 返回FFI安全的插件接口
23pub type CreatePluginFn = unsafe extern "C" fn() -> *mut PluginInterface;
24
25/// 插件销毁函数类型
26/// 销毁插件接口
27pub type DestroyPluginFn = unsafe extern "C" fn(*mut PluginInterface);
28
29/// 插件导出符号名称
30pub const CREATE_PLUGIN_SYMBOL: &[u8] = b"create_plugin";
31pub const DESTROY_PLUGIN_SYMBOL: &[u8] = b"destroy_plugin";
32
33/// 从PluginHandler trait对象创建FFI安全的插件接口
34/// 这个函数帮助插件开发者将trait对象转换为FFI安全的接口
35pub fn create_plugin_interface_from_handler(
36    handler: Box<dyn crate::handler::PluginHandler>
37) -> *mut PluginInterface {
38    use std::ffi::{CStr, CString};
39
40    let handler_ptr = Box::into_raw(Box::new(handler)) as *mut std::ffi::c_void;
41
42    // 定义FFI安全的函数包装器
43    unsafe extern "C" fn initialize_wrapper(ptr: *mut std::ffi::c_void, callbacks: HostCallbacks) -> i32 {
44        let handler = &*(ptr as *mut Box<dyn crate::handler::PluginHandler>);
45        match handler.initialize(callbacks) {
46            Ok(_) => 0,
47            Err(_) => -1,
48        }
49    }
50
51    unsafe extern "C" fn update_ui_wrapper(
52        ptr: *mut std::ffi::c_void,
53        ctx_ptr: *const std::ffi::c_void,
54        ui_ptr: *mut std::ffi::c_void
55    ) -> i32 {
56        let handler = &mut *(ptr as *mut Box<dyn crate::handler::PluginHandler>);
57        let ctx = &*(ctx_ptr as *const crate::pluginui::Context);
58        let ui = &mut *(ui_ptr as *mut crate::pluginui::Ui);
59
60        handler.update_ui(ctx, ui);
61        0
62    }
63
64    unsafe extern "C" fn on_mount_wrapper(ptr: *mut std::ffi::c_void, metadata_ffi: PluginMetadataFFI) -> i32 {
65        let handler = &mut *(ptr as *mut Box<dyn crate::handler::PluginHandler>);
66
67        // Convert FFI metadata back to Rust struct
68        let metadata = crate::metadata::PluginMetadata {
69            id: if !metadata_ffi.id.is_null() {
70                CStr::from_ptr(metadata_ffi.id).to_string_lossy().to_string()
71            } else {
72                String::new()
73            },
74            disabled: metadata_ffi.disabled,
75            name: if !metadata_ffi.name.is_null() {
76                CStr::from_ptr(metadata_ffi.name).to_string_lossy().to_string()
77            } else {
78                String::new()
79            },
80            description: if !metadata_ffi.description.is_null() {
81                CStr::from_ptr(metadata_ffi.description).to_string_lossy().to_string()
82            } else {
83                String::new()
84            },
85            version: if !metadata_ffi.version.is_null() {
86                CStr::from_ptr(metadata_ffi.version).to_string_lossy().to_string()
87            } else {
88                String::new()
89            },
90            author: if !metadata_ffi.author.is_null() {
91                Some(CStr::from_ptr(metadata_ffi.author).to_string_lossy().to_string())
92            } else {
93                None
94            },
95            library_path: if !metadata_ffi.library_path.is_null() {
96                Some(CStr::from_ptr(metadata_ffi.library_path).to_string_lossy().to_string())
97            } else {
98                None
99            },
100            config_path: if !metadata_ffi.config_path.is_null() {
101                CStr::from_ptr(metadata_ffi.config_path).to_string_lossy().to_string()
102            } else {
103                String::new()
104            },
105        };
106
107        match handler.on_mount(&metadata) {
108            Ok(_) => 0,
109            Err(_) => -1,
110        }
111    }
112
113    unsafe extern "C" fn on_dispose_wrapper(ptr: *mut std::ffi::c_void) -> i32 {
114        let handler = &mut *(ptr as *mut Box<dyn crate::handler::PluginHandler>);
115        match handler.on_dispose() {
116            Ok(_) => 0,
117            Err(_) => -1,
118        }
119    }
120
121    unsafe extern "C" fn on_connect_wrapper(ptr: *mut std::ffi::c_void) -> i32 {
122        let handler = &mut *(ptr as *mut Box<dyn crate::handler::PluginHandler>);
123        match handler.on_connect() {
124            Ok(_) => 0,
125            Err(_) => -1,
126        }
127    }
128
129    unsafe extern "C" fn on_disconnect_wrapper(ptr: *mut std::ffi::c_void) -> i32 {
130        let handler = &mut *(ptr as *mut Box<dyn crate::handler::PluginHandler>);
131        match handler.on_disconnect() {
132            Ok(_) => 0,
133            Err(_) => -1,
134        }
135    }
136
137    unsafe extern "C" fn handle_message_wrapper(
138        ptr: *mut std::ffi::c_void,
139        message: *const c_char,
140        result: *mut *mut c_char
141    ) -> i32 {
142        let handler = &*(ptr as *mut Box<dyn crate::handler::PluginHandler>);
143        let message_str = CStr::from_ptr(message).to_string_lossy();
144
145        match handler.handle_message(&message_str) {
146            Ok(response) => {
147                let response_cstring = CString::new(response).unwrap();
148                *result = response_cstring.into_raw();
149                0
150            }
151            Err(_) => -1,
152        }
153    }
154
155    unsafe extern "C" fn get_metadata_wrapper(ptr: *mut std::ffi::c_void) -> PluginMetadataFFI {
156        let handler = &*(ptr as *mut Box<dyn crate::handler::PluginHandler>);
157        let metadata = handler.get_metadata();
158        metadata.to_ffi()
159    }
160
161    unsafe extern "C" fn destroy_wrapper(ptr: *mut std::ffi::c_void) {
162        let _ = Box::from_raw(ptr as *mut Box<dyn crate::handler::PluginHandler>);
163    }
164
165    let interface = PluginInterface {
166        plugin_ptr: handler_ptr,
167        initialize: initialize_wrapper,
168        update_ui: update_ui_wrapper,
169        on_mount: on_mount_wrapper,
170        on_dispose: on_dispose_wrapper,
171        on_connect: on_connect_wrapper,
172        on_disconnect: on_disconnect_wrapper,
173        handle_message: handle_message_wrapper,
174        get_metadata: get_metadata_wrapper,
175        destroy: destroy_wrapper,
176    };
177
178    Box::into_raw(Box::new(interface))
179}