Rust:如何动态调用字符串定义的 Rhai 函数?
在 Rust 中使用 Rhai 脚本引擎时,你可以动态地调用传入的字符串表示的 Rhai 函数。Rhai 是一个嵌入式脚本语言,专为嵌入到 Rust 应用中而设计。以下是一个基本示例,展示了如何在 Rust 中调用用字符串传入的 Rhai 函数。
首先,确保你已经将 Rhai 添加到你的 Cargo.toml 文件中:
[dependencies]
rhai = "0.19" # 请检查最新版本号
然后,你可以使用以下代码来调用用字符串传入的 Rhai 函数:
use rhai::{Engine, EvalAltResult, FnPtr, Module, Scope};fn main() -> Result<(), Box<dyn std::error::Error>> {// 创建一个 Rhai 引擎实例let mut engine = Engine::new();// 定义一个 Rhai 模块,其中包含一些函数let mut module = Module::new();module.insert_fn("greet", |name: String| format!("Hello, {}", name));module.insert_fn("add", |a: i32, b: i32| a + b);// 将模块注册到引擎中engine.register_module(module)?;// 创建一个作用域let mut scope = Scope::new();// 示例:要调用的函数名及其参数let function_name = "greet".to_string();let args: Vec<Box<dyn FnPtr>> = vec![Box::new(|_| "World".to_string()) as Box<dyn FnPtr>];// 调用函数let result: EvalAltResult = engine.eval_expression_with_scope(&format!("({})", function_name),&mut scope,args.iter().cloned().collect::<Vec<_>>(),)?;// 打印结果match result {EvalAltResult::Value(value) => println!("Result: {}", value.render()?),_ => println!("Result is not a value"),}Ok(())
}
然而,上面的代码有一些限制和简化的地方:
- 参数传递:在上面的示例中,参数传递是通过创建一个
FnPtr的向量并传递给eval_expression_with_scope实现的。但这种方法比较繁琐,并且只适用于简单的函数签名。 - 函数名处理:函数名是通过字符串格式化直接嵌入到表达式中的,这意味着你需要确保传入的函数名是安全的(即不会导致 Rhai 执行不安全的代码)。
一个更健壮的方法是使用 Rhai 的 FnCall 功能,但这需要更多的设置和错误处理。以下是一个更通用的方法,但稍微复杂一些:
use rhai::{Engine, EvalAltResult, Module, Scope};
use rhai::serde::{Deserialize, Serialize};#[derive(Debug, Serialize, Deserialize)]
struct CallArgs {func: String,args: Vec<String>,
}fn main() -> Result<(), Box<dyn std::error::Error>> {// 创建一个 Rhai 引擎实例let mut engine = Engine::new();// 定义一个 Rhai 模块,其中包含一些函数let mut module = Module::new();module.insert_fn("greet", |name: String| format!("Hello, {}", name));module.insert_fn("add", |a: i32, b: i32| a + b);// 将模块注册到引擎中engine.register_module(module)?;// 创建一个作用域let mut scope = Scope::new();// 示例:要调用的函数名及其参数let call_args = CallArgs {func: "greet".to_string(),args: vec!["Alice".to_string()],};// 将参数转换为 Rhai 值let rhai_args: rhai::Array = call_args.args.into_iter().map(|arg| rhai::Value::from(arg)).collect();// 定义一个临时的 Rhai 函数来调用目标函数let call_code = format!(r#"fn call_func(func_name: String, args: Array) -> Any {{let func = match func_name.as_str() {{"greet" => greet,"add" => add as fn(i32, i32) -> i32,_ => return "Function not found".into(),}};match (func, args.len()) {{(greet, 1) => greet(args[0].cast::<String>()?),(add, 2) => add(args[0].cast::<i32>()?, args[1].cast::<i32>()?),_ => return "Invalid argument count".into(),}}}}call_func("{}", {})"#,call_args.func, rhai_args);// 调用函数let result: EvalAltResult = engine.eval_expression(&call_code, &mut scope)?;// 打印结果match result {EvalAltResult::Value(value) => println!("Result: {}", value.render()?),_ => println!("Result is not a value"),}Ok(())
}
在这个更通用的示例中,我们定义了一个 CallArgs 结构体来存储函数名和参数,然后构建了一个临时的 Rhai 脚本,该脚本根据函数名和参数数量调用相应的 Rhai 函数。这种方法提供了更大的灵活性,但也更复杂,并且需要处理更多的错误情况。
相关文章:
Rust:如何动态调用字符串定义的 Rhai 函数?
在 Rust 中使用 Rhai 脚本引擎时,你可以动态地调用传入的字符串表示的 Rhai 函数。Rhai 是一个嵌入式脚本语言,专为嵌入到 Rust 应用中而设计。以下是一个基本示例,展示了如何在 Rust 中调用用字符串传入的 Rhai 函数。 首先,确保…...
A星算法两元障碍物矩阵转化为rrt算法四元障碍物矩阵
对于a星算法obstacle所表示的障碍物障碍物信息,每行表示一个障碍物的坐标,例如2 , 3; % 第一个障碍物在第二行第三列,也就是边长为1的正方形障碍物右上角横坐标是2,纵坐标为3,障碍物的宽度和高度始终为1.在rrt路径规划…...
【C++】设计模式详解:单例模式
文章目录 Ⅰ. 设计一个类,不允许被拷贝Ⅱ. 请设计一个类,只能在堆上创建对象Ⅲ. 请设计一个类,只能在栈上创建对象Ⅳ. 请设计一个类,不能被继承Ⅴ. 请设计一个类,只能创建一个对象(单例模式)&am…...
单细胞分析基础-第一节 数据质控、降维聚类
scRNA_pipeline\1.Seurat 生物技能树 可进官网查询 添加链接描述 分析流程 准备:R包安装 options("repos"="https://mirrors.ustc.edu.cn/CRAN/") if(!require("BiocManager")) install.packages("BiocManager",update = F,ask =…...
多项日常使用测试,带你了解如何选择AI工具 Deepseek VS ChatGpt VS Claude
多项日常使用测试,带你了解如何选择AI工具 Deepseek VS ChatGpt VS Claude 注:因为考虑到绝大部分人的使用,我这里所用的模型均为免费模型。官方可访问的。ChatGPT这里用的是4o Ai对话,编程一直以来都是人们所讨论的话题。Ai的出现…...
每日一题-判断是否是平衡二叉树
判断是否是平衡二叉树 题目描述数据范围题解解题思路递归算法代码实现代码解析时间和空间复杂度分析示例示例 1示例 2 总结 ) 题目描述 输入一棵节点数为 n 的二叉树,判断该二叉树是否是平衡二叉树。平衡二叉树定义为: 它是一棵空树。或者它的左右子树…...
FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验
文章目录 FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验概述笔记my_fltk_test.cppfltk_test.hfltk_test.cxx用adjuster工程试了一下,好使。END FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验 概述 用fluid搭建UI…...
《多阶段渐进式图像修复》学习笔记
paper:2102.02808 GitHub:swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...
AWScurl笔记
摘要 AWScurl是一款专为与AWS服务交互设计的命令行工具,它模拟了curl的功能并添加了AWS签名版本4的支持。这一特性使得用户能够安全有效地执行带有AWS签名的请求,极大地提升了与AWS服务交互时的安全性和有效性。 GitHub - okigan/awscurl: curl-like acc…...
QT使用eigen
QT使用eigen 1. 下载eigen https://eigen.tuxfamily.org/index.php?titleMain_Page#Download 下载后解压 2. QT引入eigen eigen源码好像只有头文件,因此只需要引入头文件就好了 qt新建项目后。修改pro文件. INCLUDEPATH E:\222078\qt\eigen-3.4.0\eigen-3.…...
揭示Baklib企业内容管理系统CMS的核心功能与应用价值
内容概要 企业内容管理系统(CMS)是指通过一系列工具和技术,帮助企业高效地创建、存储、管理和分发数字内容的系统。这些系统在现代企业运作中发挥着至关重要的作用,尤其是在信息量大、业务流程复杂的环境中。Baklib作为一个突出的…...
如何跨互联网adb连接到远程手机-蓝牙电话集中维护
如何跨互联网adb连接到远程手机-蓝牙电话集中维护 --ADB连接专题 一、前言 随便找一个手机,安装一个App并简单设置一下,就可以跨互联网的ADB连接到这个手机,从而远程操控这个手机做各种操作。你敢相信吗?而这正是本篇想要描述的…...
flume和kafka整合 flume和kafka为什么一起用?
Flume和Kafka一起使用的主要原因是为了实现高效、可靠的数据采集和实时处理。12 实时流式日志处理的需求 Flume和Kafka结合使用的主要目的是为了完成实时流式的日志处理。Flume负责数据的采集和传输,而Kafka则作为消息缓存队列,能够有效地缓冲数据,防止数据堆积或丢…...
java.util.Random类(详细案例拆解)(已完结)
前言: 小编打算近期更俩三期类的专栏,一些常用的专集类,给大家分好类别总结和详细的代码举例解释。 今天是除夕,小编先祝贺大家除夕快乐啦!! 今天是第六个 java.lang.Math 包中的 java.util.Random类 我…...
Java后端之AOP
AOP:面向切面编程,本质是面向特定方法编程 引入依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>示例:记录…...
【信息系统项目管理师-选择真题】2008上半年综合知识答案和详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7~8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16~20题】【第21题】【第22题】【第23题】【第24题】【第25题…...
go到底是什么意思:对go的猜测或断言
go这个单词,简单地讲,表示“走或去”的意思: go v.去;走 认真想想,go是一个非常神秘的单词,g-和o-这两个字母,为什么就会表达“去;走”的意思呢?它的字面义或本质&…...
零刻SER7接口及配置跑分
今天入手了一台迷你机-零刻SER7 ,不得不说这机身是真的小啊,相比于传统台式机,它几乎不占空间,可以轻松放置在桌面、电视柜甚至背包中,非常适合需要频繁移动或空间有限的用户。尽管体积小巧,但零刻SER7在性…...
【Java基础-41.5】深入解析Java异常链:构建清晰的错误追踪体系
在Java编程中,异常处理是保证程序健壮性和可维护性的重要部分。然而,在实际开发中,异常往往不是孤立发生的,而是由一系列相关的异常引发的。为了更好地理解和处理这种复杂的异常场景,Java引入了 异常链(Exc…...
【Python实现机器遗忘算法】复现2023年TNNLS期刊算法UNSIR
【Python实现机器遗忘算法】复现2023年TNNLS期刊算法UNSIR 1 算法原理 Tarun A K, Chundawat V S, Mandal M, et al. Fast yet effective machine unlearning[J]. IEEE Transactions on Neural Networks and Learning Systems, 2023. 本文提出了一种名为 UNSIR(Un…...
iOS 26.4-26.5终极越狱指南:安全解锁iPhone隐藏功能与高级定制方案
iOS 26.4-26.5终极越狱指南:安全解锁iPhone隐藏功能与高级定制方案 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder 👇…...
LaTeX引用中文文献总出乱码?可能是你的.bib文件编码和编译顺序没搞对
LaTeX中文文献引用乱码全解析:从编码原理到实战排错 当你熬夜赶论文,终于把参考文献列表整理进.bib文件,满心期待地按下编译键——结果引用位置跳出一串问号,参考文献列表变成乱码战场。这种崩溃瞬间,每个用LaTeX写过中…...
基于RAG与智能体技术构建法律领域AI应用实战指南
1. 项目概述:一个法律智能体的诞生最近在GitHub上看到一个挺有意思的项目,叫mileson/moticlaw。光看这个名字,可能有点摸不着头脑,但稍微拆解一下就能明白它的野心:“motic” 很可能是 “motion”(动议、提…...
别再硬编码IP了!深入Nacos 2.x源码,看它如何‘智能’又‘犯错’地选择服务端地址
Nacos 2.x服务端IP地址选择机制深度解析与实战调优 在分布式系统架构中,服务注册与发现是微服务架构的核心基础设施。作为阿里巴巴开源的服务发现和配置管理平台,Nacos凭借其简单易用、功能强大等特点,已成为众多企业微服务架构的首选组件。…...
基于Three.js与WebSocket构建虚拟小镇:全栈技术架构与优化实践
1. 项目概述与核心价值最近在折腾一个叫“Alicization-Town”的开源项目,它来自GitHub上的ceresOPA组织。乍一看这个名字,可能会联想到某个动漫或者游戏里的场景,但实际接触后,我发现它远不止于此。这是一个围绕“虚拟小镇”或“数…...
完美解决VS Code/Cursor远程连接报错:远程主机不满足运行 VS Code 服务器的先决条件(附AI编程最佳实践)
完美解决VS Code/Cursor远程连接报错:远程主机不满足运行 VS Code 服务器的先决条件(附AI编程最佳实践) 💡 背景与痛点 最近在接手维护一个老项目,服务器是腾讯云的轻量应用服务器,装了宝塔面板。在经历了一…...
macOS LaunchAgent 开机自启服务配置实战:以 OpenClaw 为例
title: “macOS LaunchAgent 开机自启服务配置实战:以 OpenClaw 为例” tags: macOSLaunchAgent开机自启launchdOpenClaw categories:macOS description: “从原理到实战,详解 macOS LaunchAgent 的配置方法,以 OpenClaw Gateway 和 CLIProx…...
手把手教你用OpenMP和CUDA加速ICP配准:从单核到GPU的完整性能对比
手把手教你用OpenMP和CUDA加速ICP配准:从单核到GPU的完整性能对比 ICP(Iterative Closest Point)算法是点云配准领域的经典方法,但在处理大规模点云时常常面临性能瓶颈。本文将深入探讨如何利用OpenMP和CUDA技术对ICP算法进行多线…...
使用 QLineF 从 QTransform 提取角度信息
我们在对 QGraphicsItem 进行变换时,QT 提供了很多便捷的方法。但当我们想获取当前变换的角度时却有些困难,因为 QTransform 没有提供获取角度的方法。在文章Qt 从 QTransform 逆向解出 Translate/Scale/Rotate(平移/缩放/旋转)分…...
Protégé工具与OWL本体建模实践指南
1. 本体建模基础与Protg工具概述本体(Ontology)作为知识工程领域的核心概念,最初源自哲学领域,在计算机科学中被重新定义为"对共享概念体系的明确形式化规范说明"。在语义网架构中,本体位于XML和RDF层之上&a…...
