Rust轻量级插件库smol-potat的使用,smol-potat为Rust生态提供高效简洁的扩展功能
smol-potat
为smol运行时提供的proc宏。
这个宏帮助你在二进制文件、测试用例和基准测试中初始化smol运行时。使用方式类似于你在tokio和async-std中的做法。
使用方法
单线程
#[smol_potat::main]
async fn main() {
println!("Hello, world!");
}
多线程
#[smol_potat::main(threads=3)]
async fn main() {
println!("Hello, world!");
}
自动线程生成
启用auto功能后,使用方法与单线程相同:
smol_potat = { version = "1", features = ["auto"] }
#[smol_potat::main]
async fn main() {
println!("Hello, world!");
}
完整示例
下面是一个完整的示例,展示了如何使用smol-potat创建一个简单的异步应用程序:
// Cargo.toml
// [dependencies]
// smol-potat = "1.1.2"
use std::time::Duration;
// 单线程示例
#[smol_potat::main]
async fn main() {
println!("Starting single-threaded example");
// 创建一个异步任务
let task = smol::spawn(async {
println!("Task running after 1 second");
smol::Timer::after(Duration::from_secs(1)).await;
println!("Task completed");
});
task.await;
println!("Single-threaded example finished");
}
// 多线程示例
#[smol_potat::main(threads=4)]
async fn multi_thread_main() {
println!("Starting multi-threaded example with 4 threads");
// 创建多个并发任务
let tasks = (1..=5).map(|i| {
smol::spawn(async move {
println!("Task {} started", i);
smol::Timer::after(Duration::from_secs(1)).await;
println!("Task {} completed", i);
})
}).collect::<Vec<_>>();
// 等待所有任务完成
for task in tasks {
task.await;
}
println!("Multi-threaded example finished");
}
自动线程示例
要使用自动线程功能,请确保在Cargo.toml中启用了"auto"特性:
[dependencies]
smol-potat = { version = "1", features = ["auto"] }
然后可以使用与单线程相同的语法:
#[smol_potat::main]
async fn auto_thread_main() {
println!("This will automatically use multiple threads based on available CPUs");
let tasks = (1..=10).map(|i| {
smol::spawn(async move {
println!("Auto-threaded task {} started", i);
smol::Timer::after(Duration::from_secs(1)).await;
println!("Auto-threaded task {} completed", i);
})
}).collect::<Vec<_>>();
for task in tasks {
task.await;
}
println!("Auto-threaded example finished");
}
1 回复
Rust轻量级插件库smol-potat使用指南
简介
smol-potat是一个轻量级的Rust插件库,旨在为Rust生态系统提供高效简洁的扩展功能。它的设计理念是保持核心简单,同时提供足够的灵活性来扩展应用功能。
主要特性
- 极简API设计
- 低开销插件系统
- 线程安全实现
- 无额外依赖
- 支持热加载(实验性)
安装
在Cargo.toml中添加依赖:
[dependencies]
smol-potat = "0.2"
基本使用
1. 定义插件
use smol_potat::{Plugin, PluginResult};
struct MyPlugin;
impl Plugin for MyPlugin {
fn name(&self) -> &str {
"my_plugin"
}
fn execute(&self, input: &str) -> PluginResult<String> {
Ok(format!("Processed: {}", input))
}
}
2. 注册和使用插件
use smol_potat::PluginManager;
fn main() {
let mut manager = PluginManager::new();
// 注册插件
manager.register(Box::new(MyPlugin));
// 使用插件
if let Some(result) = manager.execute("my_plugin", "hello") {
match result {
Ok(output) => println!("{}", output),
Err(e) => eprintln!("Error: {}", e),
}
} else {
println!("Plugin not found");
}
}
高级功能
动态加载插件(实验性)
#[cfg(feature = "dynamic")]
fn load_dynamic_plugin() {
use smol_potat::DynamicPluginLoader;
let loader = DynamicPluginLoader::new();
if let Ok(plugin) = loader.load("path/to/plugin.so") {
let mut manager = PluginManager::new();
manager.register(plugin);
// 使用动态加载的插件...
}
}
插件间通信
use smol_potat::{Plugin, PluginResult, PluginContext};
struct CommunicatingPlugin;
impl Plugin for CommunicatingPlugin {
fn name(&self) -> &str {
"communicator"
}
fn execute(&self, input: &str) -> PluginResult<String> {
// 通过上下文访问其他插件
if let Some(ctx) = self.context() {
if let Some(other_result) = ctx.execute("other_plugin", input) {
// 处理其他插件的结果...
}
}
Ok("Done".into())
}
}
性能建议
- 对于高频调用的插件,考虑实现
Plugin
trait的execute_mut
方法以避免内部锁开销 - 使用
#[inline]
标记小型插件函数 - 考虑使用
&'static str
而不是String
作为插件名称
示例项目结构
my_app/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── plugins/
│ │ ├── mod.rs
│ │ ├── my_plugin.rs
│ │ └── other_plugin.rs
注意事项
- 当前版本(0.2)API仍可能变化
- 动态加载功能需要
dynamic
特性标志 - 生产环境使用前请充分测试插件隔离性
完整示例Demo
下面是一个完整的smol-potat使用示例,包含多个插件和主程序实现:
// src/main.rs
use smol_potat::PluginManager;
mod plugins;
fn main() {
let mut manager = PluginManager::new();
// 注册内置插件
manager.register(Box::new(plugins::my_plugin::MyPlugin));
manager.register(Box::new(plugins::greeter::GreeterPlugin));
// 使用插件
if let Some(result) = manager.execute("my_plugin", "test input") {
match result {
Ok(output) => println!("MyPlugin结果: {}", output),
Err(e) => eprintln!("MyPlugin错误: {}", e),
}
}
if let Some(result) = manager.execute("greeter", "Rust开发者") {
match result {
Ok(output) => println!("GreeterPlugin结果: {}", output),
Err(e) => eprintln!("GreeterPlugin错误: {}", e),
}
}
}
// src/plugins/mod.rs
pub mod my_plugin;
pub mod greeter;
// src/plugins/my_plugin.rs
use smol_potat::{Plugin, PluginResult};
pub struct MyPlugin;
impl Plugin for MyPlugin {
fn name(&self) -> &str {
"my_plugin"
}
fn execute(&self, input: &str) -> PluginResult<String> {
// 简单的处理逻辑 - 反转字符串
Ok(input.chars().rev().collect())
}
}
// src/plugins/greeter.rs
use smol_potat::{Plugin, PluginResult};
pub struct GreeterPlugin;
impl Plugin for GreeterPlugin {
fn name(&self) -> &str {
"greeter"
}
fn execute(&self, input: &str) -> PluginResult<String> {
// 问候语生成
Ok(format!("你好, {}! 欢迎使用smol-potat插件系统!", input))
}
}
# Cargo.toml
[package]
name = "smol-potat-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
smol-potat = "0.2"
这个完整示例展示了:
- 项目结构组织
- 多个插件的定义和实现
- 主程序如何注册和使用插件
- 基本的错误处理
要运行此示例,只需创建相应目录结构,添加上述文件,然后运行cargo run
即可。