Merge pull request #4031 from Kingtous/feat/plugins

feat: add a rust example for writing a custom plugin
This commit is contained in:
RustDesk
2023-04-13 09:25:46 +08:00
committed by GitHub
7 changed files with 103 additions and 33 deletions

View File

@@ -8,8 +8,8 @@ pub type UnloadPluginFunc = fn(*const c_char) -> i32;
#[repr(C)]
pub struct RustDeskApiTable {
pub register_plugin: LoadPluginFunc,
pub unload_plugin: UnloadPluginFunc,
pub(crate) register_plugin: LoadPluginFunc,
pub(crate) unload_plugin: UnloadPluginFunc,
}
#[no_mangle]
@@ -22,11 +22,6 @@ fn unload_plugin(path: *const c_char) -> i32 {
PLUGIN_REGISTRAR.unload_plugin(path)
}
#[no_mangle]
fn get_api_table() -> RustDeskApiTable {
RustDeskApiTable::default()
}
impl Default for RustDeskApiTable {
fn default() -> Self {
Self {

View File

@@ -1,7 +1,7 @@
mod keyboard;
#[cfg(not(any(target_os = "ios")))]
/// cbindgen:ignore
pub mod platform;
mod keyboard;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub use platform::{get_cursor, get_cursor_data, get_cursor_pos, start_os_service};
#[cfg(not(any(target_os = "ios")))]
@@ -20,7 +20,12 @@ pub use self::rendezvous_mediator::*;
pub mod common;
#[cfg(not(any(target_os = "ios")))]
pub mod ipc;
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli", feature = "flutter")))]
#[cfg(not(any(
target_os = "android",
target_os = "ios",
feature = "cli",
feature = "flutter"
)))]
pub mod ui;
mod version;
pub use version::*;
@@ -44,9 +49,9 @@ mod license;
mod port_forward;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
mod plugins;
pub mod api;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
mod api;
pub mod plugins;
mod tray;

View File

@@ -4,7 +4,10 @@ use std::{
sync::{Arc, RwLock},
};
use hbb_common::{anyhow::Error, log::debug};
use hbb_common::{
anyhow::Error,
log::{debug, error},
};
use lazy_static::lazy_static;
use libloading::{Library, Symbol};
@@ -82,6 +85,18 @@ impl<P: Plugin> PluginRegistar<P> {
match lib {
Ok(lib) => match lib.try_into() {
Ok(plugin) => {
let plugin: PluginImpl = plugin;
// try to initialize this plugin
if let Some(init) = plugin.plugin_vt().init {
let init_ret = init();
if init_ret != 0 {
error!(
"Error when initializing the plugin {} with error code {}.",
plugin.name, init_ret
);
return init_ret;
}
}
PLUGIN_REGISTRAR
.plugins
.write()
@@ -104,7 +119,12 @@ impl<P: Plugin> PluginRegistar<P> {
let p = unsafe { CStr::from_ptr(path) };
let lib_path = p.to_str().unwrap_or("").to_owned();
match PLUGIN_REGISTRAR.plugins.write().unwrap().remove(&lib_path) {
Some(_) => 0,
Some(plugin) => {
if let Some(dispose) = plugin.plugin_vt().dispose {
return dispose();
}
0
}
None => -1,
}
}
@@ -150,33 +170,28 @@ impl TryFrom<Library> for PluginImpl {
#[cfg(target_os = "linux")]
fn test_plugin() {
use std::io::Write;
let code = "
const char* plugin_name(){return \"test_name\";};
const char* plugin_id(){return \"test_id\"; }
int plugin_init() {return 0;}
int plugin_dispose() {return 0;}
";
let mut f = std::fs::File::create("test.c").unwrap();
f.write_all(code.as_bytes()).unwrap();
f.flush().unwrap();
let mut cmd = std::process::Command::new("cc");
cmd.arg("-fPIC")
.arg("-shared")
.arg("test.c")
.arg("-o")
.arg("libtest.so");
let mut cmd = std::process::Command::new("cargo");
cmd.current_dir("./examples/custom_plugin");
// Strip this shared library.
cmd.env("RUSTFLAGS", "-C link-arg=-s");
cmd.arg("build");
// Spawn the compiler process.
let mut child = cmd.spawn().unwrap();
// Wait for the compiler to finish.
let status = child.wait().unwrap();
assert!(status.success());
// Load the library.
let lib = unsafe { Library::new("./libtest.so").unwrap() };
let lib = unsafe {
Library::new("./examples/custom_plugin/target/debug/libcustom_plugin.so").unwrap()
};
let plugin: PluginImpl = lib.try_into().unwrap();
assert!(plugin._inner.is_some());
assert!(plugin.name == "test_name");
assert!(plugin.id == "test_id");
assert!(plugin.name == "A Template Rust Plugin");
assert!(plugin.id == "TemplatePlugin");
println!(
"plugin vt size: {}",
std::mem::size_of::<RustDeskPluginTable>()
);
assert!(PLUGIN_REGISTRAR
.plugins
.write()