Rust轻量级插件库smol-potat的使用,smol-potat为Rust生态提供高效简洁的扩展功能

smol-potat

crates.io版本 许可证

为smol运行时提供的proc宏。

smol-potat图片

这个宏帮助你在二进制文件、测试用例和基准测试中初始化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())
    }
}

性能建议

  1. 对于高频调用的插件,考虑实现Plugin trait的execute_mut方法以避免内部锁开销
  2. 使用#[inline]标记小型插件函数
  3. 考虑使用&'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"

这个完整示例展示了:

  1. 项目结构组织
  2. 多个插件的定义和实现
  3. 主程序如何注册和使用插件
  4. 基本的错误处理

要运行此示例,只需创建相应目录结构,添加上述文件,然后运行cargo run即可。

回到顶部