Add Engine::call_fn_dynamic.
This commit is contained in:
parent
5f727335a6
commit
76d792011f
10
README.md
10
README.md
@ -341,6 +341,16 @@ let result: i64 = engine.call_fn(&mut scope, &ast, "hello", () )?;
|
||||
let result: () = engine.call_fn(&mut scope, &ast, "hidden", ())?;
|
||||
```
|
||||
|
||||
For more control, construct all arguments as `Dynamic` values and use `Engine::call_fn_dynamic`:
|
||||
|
||||
```rust
|
||||
let result: Dynamic = engine.call_fn_dynamic(&mut scope, &ast, "hello",
|
||||
&mut [ String::from("abc").into(), 123_i64.into() ])?;
|
||||
```
|
||||
|
||||
However, beware that `Engine::call_fn_dynamic` _consumes_ its arguments, meaning that all arguments passed to it
|
||||
will be replaced by `()` afterwards. To re-use the arguments, clone them beforehand and pass in the clone.
|
||||
|
||||
### Creating Rust anonymous functions from Rhai script
|
||||
|
||||
[`Func`]: #creating-rust-anonymous-functions-from-rhai-script
|
||||
|
@ -41,6 +41,7 @@ New features
|
||||
* Set limit on maximum level of nesting expressions and statements to avoid panics during parsing.
|
||||
* New `EvalPackage` to disable `eval`.
|
||||
* `Module::set_getter_fn`, `Module::set_setter_fn` and `Module:set_indexer_fn` to register getter/setter/indexer functions.
|
||||
* `Engine::call_fn_dynamic` for more control in calling script functions.
|
||||
|
||||
Speed enhancements
|
||||
------------------
|
||||
@ -60,6 +61,8 @@ Speed enhancements
|
||||
excessive cloning. For example, if `a` is a large array, getting its length in this manner: `len(a)` used to result
|
||||
in a full clone of `a` before taking the length and throwing the copy away. Now, `a` is simply passed by reference,
|
||||
avoiding the cloning altogether.
|
||||
* A custom hasher simply passes through `u64` keys without hashing to avoid function call hash keys
|
||||
(which as by themselves `u64`) being hashed twice.
|
||||
|
||||
|
||||
Version 0.14.1
|
||||
|
73
src/api.rs
73
src/api.rs
@ -997,6 +997,7 @@ impl Engine {
|
||||
}
|
||||
|
||||
/// Call a script function defined in an `AST` with multiple arguments.
|
||||
/// Arguments are passed as a tuple.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -1040,6 +1041,67 @@ impl Engine {
|
||||
args: A,
|
||||
) -> Result<T, Box<EvalAltResult>> {
|
||||
let mut arg_values = args.into_vec();
|
||||
let result = self.call_fn_dynamic(scope, ast, name, arg_values.as_mut())?;
|
||||
|
||||
let return_type = self.map_type_name(result.type_name());
|
||||
|
||||
return result.try_cast().ok_or_else(|| {
|
||||
Box::new(EvalAltResult::ErrorMismatchOutputType(
|
||||
return_type.into(),
|
||||
Position::none(),
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
/// Call a script function defined in an `AST` with multiple `Dynamic` arguments.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||
/// This is to avoid unnecessarily cloning the arguments.
|
||||
/// Do you use the arguments after this call. If you need them afterwards,
|
||||
/// clone them _before_ calling this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||
/// # #[cfg(not(feature = "no_function"))]
|
||||
/// # {
|
||||
/// use rhai::{Engine, Scope};
|
||||
///
|
||||
/// let engine = Engine::new();
|
||||
///
|
||||
/// let ast = engine.compile(r"
|
||||
/// fn add(x, y) { len(x) + y + foo }
|
||||
/// fn add1(x) { len(x) + 1 + foo }
|
||||
/// fn bar() { foo/2 }
|
||||
/// ")?;
|
||||
///
|
||||
/// let mut scope = Scope::new();
|
||||
/// scope.push("foo", 42_i64);
|
||||
///
|
||||
/// // Call the script-defined function
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add", &mut [ String::from("abc").into(), 123_i64.into() ])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 168);
|
||||
///
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add1", &mut [ String::from("abc").into() ])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 46);
|
||||
///
|
||||
/// let result= engine.call_fn_dynamic(&mut scope, &ast, "bar", &mut [])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 21);
|
||||
/// # }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub fn call_fn_dynamic(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
ast: &AST,
|
||||
name: &str,
|
||||
arg_values: &mut [Dynamic],
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||
let lib = ast.lib();
|
||||
let pos = Position::none();
|
||||
@ -1051,16 +1113,7 @@ impl Engine {
|
||||
let mut state = State::new();
|
||||
let args = args.as_mut();
|
||||
|
||||
let result = self.call_script_fn(scope, &mut state, &lib, name, fn_def, args, pos, 0)?;
|
||||
|
||||
let return_type = self.map_type_name(result.type_name());
|
||||
|
||||
return result.try_cast().ok_or_else(|| {
|
||||
Box::new(EvalAltResult::ErrorMismatchOutputType(
|
||||
return_type.into(),
|
||||
pos,
|
||||
))
|
||||
});
|
||||
self.call_script_fn(scope, &mut state, &lib, name, fn_def, args, pos, 0)
|
||||
}
|
||||
|
||||
/// Optimize the `AST` with constants defined in an external Scope.
|
||||
|
Loading…
Reference in New Issue
Block a user