Rust插件库argyle的使用:高效灵活的插件系统扩展库
Rust插件库argyle的使用:高效灵活的插件系统扩展库
Argyle是一个简单的流式CLI参数解析器/迭代器,提供了介于标准库的std::env::args_os
和完整服务库如clap之间的中间解决方案。
功能特点
- 执行基本规范化处理
- 以非panic方式处理字符串转换
- 识别简写值赋值如
-kval
、-k=val
、--key=val
- 处理命令结束(
--
)参数 - 帮助识别应用程序预期的特殊键/值
安装
在Cargo.toml
的dependencies
中添加:
[dependencies]
argyle = "0.13.*"
示例代码
以下是内容中提供的示例:
use argyle::{Argument, KeyWord};
use std::path::PathBuf;
#[derive(Debug, Clone, Default)]
/// # Configuration.
struct Settings {
threads: usize,
verbose: bool,
paths: Vec<PathBuf>,
}
let args = argyle::args()
.with_keywords([
KeyWord::key("-h").unwrap(), // Boolean flag (short).
KeyWord::key("--help").unwrap(), // Boolean flag (long).
KeyWord::key_with_value("-j").unwrap(), // Expects a value.
KeyWord::key_with_value("--threads").unwrap(),
]);
// Loop and handle!
let mut settings = Settings::default();
for arg in args {
match arg {
// Help flag match.
Argument::Key("-h" | "--help") => {
println!("Help Screen Goes Here.");
return;
},
// Thread option match.
Argument::KeyWithValue("-j" | "--threads", value) => {
settings.threads = value.parse()
.expect("Maximum threads must be a number!");
},
// Something else.
Argument::Other(v) => {
settings.paths.push(PathBuf::from(v));
},
// Also something else, but not String-able. PathBuf doesn't care
// about UTF-8, though, so it might be fine!
Argument::InvalidUtf8(v) => {
settings.paths.push(PathBuf::from(v));
},
// Nothing else is relevant here.
_ => {},
}
}
// Now that you're set up, do stuff…
完整示例demo
基于上述示例,这里是一个更完整的命令行参数处理demo:
use argyle::{Argument, KeyWord};
use std::path::PathBuf;
#[derive(Debug, Clone, Default)]
struct AppConfig {
threads: usize,
verbose: bool,
input_files: Vec<PathBuf>,
output_dir: Option<PathBuf>,
}
fn main() {
// 定义支持的参数
let args = argyle::args()
.with_keywords([
KeyWord::key("-h").unwrap(), // 帮助标志(短)
KeyWord::key("--help").unwrap(), // 帮助标志(长)
KeyWord::key("-v").unwrap(), // 详细模式标志
KeyWord::key("--verbose").unwrap(), // 详细模式标志
KeyWord::key_with_value("-j").unwrap(), // 线程数
KeyWord::key_with_value("--threads").unwrap(),
KeyWord::key_with_value("-o").unwrap(), // 输出目录
KeyWord::key_with_value("--output").unwrap(),
]);
let mut config = AppConfig {
threads: 4, // 默认4个线程
..Default::default()
};
// 处理参数
for arg in args {
match arg {
// 帮助标志
Argument::Key("-h" | "--help") => {
print_help();
return;
},
// 详细模式标志
Argument::Key("-v" | "--verbose") => {
config.verbose = true;
},
// 线程数设置
Argument::KeyWithValue("-j" | "--threads", value) => {
config.threads = value.parse()
.expect("线程数必须是正整数!");
},
// 输出目录设置
Argument::KeyWithValue("-o" | "--output", value) => {
config.output_dir = Some(PathBuf::from(value));
},
// 输入文件
Argument::Other(v) => {
config.input_files.push(PathBuf::from(v));
},
// 非UTF-8路径
Argument::InvalidUtf8(v) => {
config.input_files.push(PathBuf::from(v));
},
// 忽略其他参数
_ => {},
}
}
// 检查是否有输入文件
if config.input_files.is_empty() {
eprintln!("错误: 未指定输入文件");
print_help();
std::process::exit(1);
}
// 使用配置运行程序
run_app(config);
}
fn print_help() {
println!("用法: myapp [选项] 输入文件...");
println!();
println!("选项:");
println!(" -h, --help 显示帮助信息");
println!(" -v, --verbose 启用详细输出");
println!(" -j, --threads N 设置线程数 (默认: 4)");
println!(" -o, --output DIR 设置输出目录");
}
fn run_app(config: AppConfig) {
println!("运行配置: {:?}", config);
// 这里实现实际的应用程序逻辑
// ...
}
特性
可以通过启用非默认的try_paths
特性来暴露额外的Argument::Path
变体,用于未关联且未识别的值,其中std::fs::exists() == Ok(true)
。
许可证
本项目采用WTFPL许可证。
1 回复
Rust插件库argyle的使用:高效灵活的插件系统扩展库
介绍
argyle是一个Rust语言的插件系统扩展库,它提供了高效灵活的插件管理功能。这个库特别适合需要动态加载和卸载功能模块的应用场景,如编辑器、游戏引擎或任何需要扩展性的应用程序。
argyle的主要特点包括:
- 类型安全的插件接口
- 跨平台支持
- 低开销设计
- 灵活的插件生命周期管理
- 支持热重载
使用方法
基本使用
首先在Cargo.toml中添加依赖:
[dependencies]
argyle = "0.3"
定义插件接口
use argyle::ArgylePlugin;
// 定义插件trait
pub trait GreeterPlugin: ArgylePlugin {
fn greet(&self, name: &str) -> String;
}
实现插件
use argyle::{ArgylePlugin, PluginMetadata};
use std::path::Path;
struct HelloPlugin;
impl ArgylePlugin for HelloPlugin {
fn metadata(&self) -> PluginMetadata {
PluginMetadata {
name: "Hello Plugin".into(),
version: "1.0".into(),
}
}
}
impl GreeterPlugin for HelloPlugin {
fn greet(&self, name: &str) -> String {
format!("Hello, {}!", name)
}
}
// 导出插件工厂函数
#[no_mangle]
pub extern "C" fn _argyle_create_plugin() -> Box<dyn GreeterPlugin> {
Box::new(HelloPlugin)
}
加载和使用插件
use argyle::PluginLoader;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建插件加载器
let mut loader = PluginLoader::<dyn GreeterPlugin>::new();
// 加载插件
let plugin = unsafe { loader.load(Path::new("target/debug/libhello_plugin.so"))? };
// 使用插件
println!("{}", plugin.greet("Rustacean"));
// 卸载插件
loader.unload(plugin);
Ok(())
}
高级功能:插件热重载
use argyle::{PluginLoader, HotReloadMode};
use std::path::Path;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut loader = PluginLoader::<dyn GreeterPlugin>::new()
.with_hot_reload(HotReloadMode::Interval(Duration::from_secs(1)));
let plugin = unsafe { loader.load(Path::new("target/debug/libhello_plugin.so"))? };
loop {
println!("{}", plugin.greet("World"));
std::thread::sleep(Duration::from_secs(2));
}
}
完整示例demo
下面是一个完整的argyle插件系统示例,包含主程序和插件实现:
1. 创建主程序项目
cargo new argyle_demo
cd argyle_demo
编辑Cargo.toml:
[package]
name = "argyle_demo"
version = "0.1.0"
edition = "2021"
[dependencies]
argyle = "0.3"
2. 创建插件项目
cargo new --lib hello_plugin
cd hello_plugin
编辑Cargo.toml:
[package]
name = "hello_plugin"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
argyle = "0.3"
3. 实现插件
编辑src/lib.rs:
use argyle::{ArgylePlugin, PluginMetadata};
// 定义插件接口
pub trait GreeterPlugin: ArgylePlugin {
fn greet(&self, name: &str) -> String;
}
// 插件实现
struct HelloPlugin;
impl ArgylePlugin for HelloPlugin {
fn metadata(&self) -> PluginMetadata {
PluginMetadata {
name: "Hello Plugin".into(),
version: "1.0".into(),
}
}
}
impl GreeterPlugin for HelloPlugin {
fn greet(&self, name: &str) -> String {
format!("Hello from plugin, {}!", name)
}
}
// 导出插件工厂函数
#[no_mangle]
pub extern "C" fn _argyle_create_plugin() -> Box<dyn GreeterPlugin> {
Box::new(HelloPlugin)
}
4. 实现主程序
编辑主项目的src/main.rs:
use argyle::PluginLoader;
use std::path::Path;
// 需要与插件中相同的trait定义
pub trait GreeterPlugin: argyle::ArgylePlugin {
fn greet(&self, name: &str) -> String;
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 构建插件路径
let plugin_path = Path::new("../hello_plugin/target/debug/")
.join(format!("{}hello_plugin.{}",
if cfg!(windows) { "" } else { "lib" },
if cfg!(windows) { "dll" } else if cfg!(target_os = "macos") { "dylib" } else { "so" }
));
println!("Loading plugin from: {:?}", plugin_path);
// 创建并加载插件
let mut loader = PluginLoader::<dyn GreeterPlugin>::new();
let plugin = unsafe { loader.load(&plugin_path)? };
// 使用插件功能
println!("{}", plugin.greet("Rust Developer"));
// 卸载插件
loader.unload(plugin);
Ok(())
}
5. 构建和运行
首先构建插件:
cd hello_plugin
cargo build
然后运行主程序:
cd ../argyle_demo
cargo run
注意事项
- 插件需要编译为动态库(
.so
、.dll
或.dylib
) - 跨平台使用时要注意ABI兼容性
- 热重载功能在开发环境中特别有用,但生产环境可能需要禁用
- 确保插件和主程序使用相同版本的Rust编译器
argyle为Rust应用程序提供了强大的插件系统支持,通过合理使用可以极大地提高应用程序的扩展性和灵活性。