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", ())?;
|
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
|
### Creating Rust anonymous functions from Rhai script
|
||||||
|
|
||||||
[`Func`]: #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.
|
* Set limit on maximum level of nesting expressions and statements to avoid panics during parsing.
|
||||||
* New `EvalPackage` to disable `eval`.
|
* New `EvalPackage` to disable `eval`.
|
||||||
* `Module::set_getter_fn`, `Module::set_setter_fn` and `Module:set_indexer_fn` to register getter/setter/indexer functions.
|
* `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
|
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
|
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,
|
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.
|
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
|
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.
|
/// Call a script function defined in an `AST` with multiple arguments.
|
||||||
|
/// Arguments are passed as a tuple.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -1040,6 +1041,67 @@ impl Engine {
|
|||||||
args: A,
|
args: A,
|
||||||
) -> Result<T, Box<EvalAltResult>> {
|
) -> Result<T, Box<EvalAltResult>> {
|
||||||
let mut arg_values = args.into_vec();
|
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 mut args: StaticVec<_> = arg_values.iter_mut().collect();
|
||||||
let lib = ast.lib();
|
let lib = ast.lib();
|
||||||
let pos = Position::none();
|
let pos = Position::none();
|
||||||
@ -1051,16 +1113,7 @@ impl Engine {
|
|||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
let args = args.as_mut();
|
let args = args.as_mut();
|
||||||
|
|
||||||
let result = self.call_script_fn(scope, &mut state, &lib, name, fn_def, args, pos, 0)?;
|
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,
|
|
||||||
))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optimize the `AST` with constants defined in an external Scope.
|
/// Optimize the `AST` with constants defined in an external Scope.
|
||||||
|
Loading…
Reference in New Issue
Block a user