Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Candle Rust API

Rust 绑定,用于在 Rust 应用中嵌入 Candle 脚本引擎

概述

candle crate 提供了类型安全的 Rust API,允许你在 Rust 项目中嵌入和执行 Candle 脚本。

特性

  • 类型安全 - 完整的 Rust 类型系统支持
  • 零成本抽象 - 直接调用 C ABI,无运行时开销
  • 内存安全 - RAII 资源管理,自动 GC 根管理
  • 易于使用 - 符合 Rust 惯用法的 API
  • 完整文档 - 所有公开 API 都有文档注释

快速开始

添加依赖

[dependencies]
candle = { path = "../include" }

基础使用

use candle::{Runtime, Value};

fn main() -> candle::Result<()> {
    // 创建运行时
    let mut rt = Runtime::new();

    // 创建值
    let s = Value::string("Hello, Candle!");
    let num = Value::int(42);
    let list = rt.create_list::<i64>();
    let map = rt.create_map::<String, i64>();

    Ok(())
}

API 概览

Runtime - 运行时环境

let mut rt = Runtime::new();

// 创建各种值
let string = rt.create_string("hello");
let list = rt.create_list::<i64>();
let map = rt.create_map::<String, i64>();

// 手动触发 GC
rt.collect_garbage();

Value - 值类型

// 创建值
let null = Value::null();
let boolean = Value::bool(true);
let integer = Value::int(42);
let string = Value::string("hello");

// 类型检查
if value.is_int() {
    let num = value.as_int()?;
    println!("{}", num);
}

// 获取类型
match value.value_type() {
    ValueType::Int => println!("整数"),
    ValueType::String => println!("字符串"),
    _ => println!("其他类型"),
}

CandleString - 字符串

let s = Value::string("Hello, World!");
let candle_str = s.as_string()?;

// 属性
println!("长度: {}", candle_str.len());
println!("是否为空: {}", candle_str.is_empty());

// 方法
let sub = candle_str.substring(0, 5)?;
println!("包含 'World': {}", candle_str.contains("World"));
println!("以 'Hello' 开头: {}", candle_str.starts_with("Hello"));
println!("以 '!' 结尾: {}", candle_str.ends_with("!"));

// 转换为 Rust String
let rust_str = candle_str.to_string();

CandleList - 列表

let list = rt.create_list::<i64>();
let mut candle_list = list.as_list()?;

// 添加元素
candle_list.add(Value::int(10));
candle_list.add(Value::int(20));

// 访问元素
let first = candle_list.get(0)?;
candle_list.set(0, Value::int(100))?;

// 查询
println!("长度: {}", candle_list.len());
println!("包含 20: {}", candle_list.contains(&Value::int(20)));

// 移除元素
let removed = candle_list.remove(&Value::int(20));

// 迭代
for val in candle_list.iter() {
    if let Ok(num) = val.as_int() {
        println!("{}", num);
    }
}

// 转换为 Vec
let vec = candle_list.to_vec();

CandleMap - 映射

let map = rt.create_map::<String, i64>();
let mut candle_map = map.as_map()?;

// 设置键值对
candle_map.set_str("age", Value::int(30));
candle_map.set_str("score", Value::int(95));

// 获取值
if let Ok(age) = candle_map.get_str("age") {
    println!("年龄: {}", age.as_int()?);
}

// 查询
println!("长度: {}", candle_map.len());
println!("包含 'age': {}", candle_map.contains_str("age"));

// 移除
let removed = candle_map.remove_str("score");

// 获取所有键和值
let keys = candle_map.keys();
let values = candle_map.values();

错误处理

use candle::Error;

match value.as_int() {
    Ok(num) => println!("整数: {}", num),
    Err(Error::TypeError { expected, actual }) => {
        println!("类型错误: 期望 {}, 实际 {:?}", expected, actual);
    }
    Err(e) => println!("其他错误: {}", e),
}

使用场景

1. 配置语言

// 使用 Candle 替代 JSON/TOML
let config = rt.eval(r#"
    String app_name = "MyApp";
    int port = 8080;
    bool debug = true;
"#)?;

2. 业务规则引擎

// 允许非程序员编写业务规则
let rules = rt.eval(r#"
    int calculate_discount(int amount, bool is_vip) {
        if (is_vip && amount > 1000) return 20;
        if (amount > 500) return 5;
        return 0;
    }
"#)?;

3. 插件系统

// 用户提供的插件脚本
let plugin = rt.eval(r#"
    class MyPlugin {
        String process(String data) {
            return data + " (processed)";
        }
    }
"#)?;

4. 表达式求值

// 动态表达式计算
let result = rt.eval("(10 + 20) * 3")?;
println!("{}", result.as_int()?);

5. 脚本化测试

// 使用脚本描述测试场景
let test = rt.eval(r#"
    List<int> numbers = List<int>();
    numbers.add(1);
    numbers.add(2);
    numbers.add(3);
    assert(numbers.length == 3);
"#)?;

示例程序

查看 examples/ 目录:

  • hello.rs - 基础 API 使用
  • eval.rs - 脚本执行示例
  • embedding.rs - 嵌入式应用场景

运行示例:

cd include
cargo run --example hello
cargo run --example eval
cargo run --example embedding

架构

Rust 应用程序
    ↓ 使用
Candle Rust API (include/)
    ↓ 调用
Candle Runtime (C ABI)
    ↓ 执行
Candle VM

内存管理

  • 自动 GC - Candle 值由 GC 管理
  • RAII - Rust 端自动管理 GC 根
  • 引用计数 - Value 类型实现了 Clone 和 Drop
{
    let s = Value::string("hello");
    // 自动调用 candle_rt_gc_add_root
    
    let s2 = s.clone();
    // 增加引用计数
    
} // 自动调用 candle_rt_gc_remove_root

性能

  • ✅ 零成本抽象 - 直接调用 C ABI
  • ✅ 编译时优化 - LLVM 优化
  • ✅ 无运行时开销 - 没有额外的包装层

线程安全

⚠️ 当前版本不是线程安全的

  • Runtime 不实现 SendSync
  • 每个线程需要自己的 Runtime 实例
  • 未来版本可能添加线程安全支持

构建要求

  • Rust 1.70+
  • Candle 运行时库 (libcandle_runtime.a)

开发状态

🚧 实验性版本

当前版本提供了完整的 API 接口设计,但部分功能(如 eval)需要完整的编译器运行时集成才能工作。

已实现:

  • ✅ 类型安全的 Value 封装
  • ✅ String、List、Map 操作
  • ✅ 内存管理(GC 根)
  • ✅ 错误处理

待实现:

  • ⏳ eval 脚本执行
  • ⏳ 函数调用
  • ⏳ 全局变量访问
  • ⏳ 异常捕获

贡献

欢迎贡献!主要需要:

  1. 完善运行时集成(eval 功能)
  2. 添加更多测试
  3. 改进文档
  4. 性能优化

许可证

MIT License

相关项目

  • mlua - Lua 的 Rust 绑定
  • rquickjs - QuickJS 的 Rust 绑定
  • pyo3 - Python 的 Rust 绑定

Candle - 现代、高性能的脚本语言