Allow NativeCallContext in function arguments.
This commit is contained in:
@@ -334,6 +334,85 @@ mod my_module {
|
||||
```
|
||||
|
||||
|
||||
`NativeCallContext` Parameter
|
||||
----------------------------
|
||||
|
||||
If the _first_ parameter of a function is of type `rhai::NativeCallContext`, then it is treated
|
||||
specially by the plugins system.
|
||||
|
||||
`NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following:
|
||||
|
||||
* `NativeCallContext::engine(): &Engine` - the current [`Engine`], with all configurations and settings.
|
||||
This is sometimes useful for calling a script-defined function within the same evaluation context
|
||||
using [`Engine::call_fn`][`call_fn`].
|
||||
|
||||
* `NativeCallContext::namespace(): &Module` - the global namespace of script-defined functions, as a [`Module`].
|
||||
|
||||
This first parameter, if exists, will be stripped before all other processing. It is _virtual_.
|
||||
Most importantly, it does _not_ count as a parameter to the function and there is no need to provide
|
||||
this argument when calling the function in Rhai.
|
||||
|
||||
The native call context can be used to call a [function pointer] or [closure] that has been passed
|
||||
as a parameter to the function, thereby implementing a _callback_:
|
||||
|
||||
```rust
|
||||
use rhai::{Dynamic, FnPtr, NativeCallContext, EvalAltResult};
|
||||
use rhai::plugin::*; // a "prelude" import for macros
|
||||
|
||||
#[export_module]
|
||||
mod my_module {
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn greet(context: NativeCallContext, callback: FnPtr)
|
||||
-> Result<Dynamic, Box<EvalAltResult>>
|
||||
{
|
||||
// Call the callback closure with the current context
|
||||
// to obtain the name to greet!
|
||||
let name = callback.call_dynamic(context, None, [])?;
|
||||
Ok(format!("hello, {}!", name).into())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The native call context is also useful in another scenario: protecting a function from malicious scripts.
|
||||
|
||||
```rust
|
||||
use rhai::{Dynamic, INT, Array, NativeCallContext, EvalAltResult, Position};
|
||||
use rhai::plugin::*; // a "prelude" import for macros
|
||||
|
||||
#[export_module]
|
||||
mod my_module {
|
||||
// This function builds an array of arbitrary size, but is protected
|
||||
// against attacks by first checking with the allowed limit set
|
||||
// into the 'Engine'.
|
||||
#[rhai_fn(return_raw)]
|
||||
pub fn grow(context: NativeCallContext, size: INT)
|
||||
-> Result<Dynamic, Box<EvalAltResult>>
|
||||
{
|
||||
// Make sure the function does not generate a
|
||||
// data structure larger than the allowed limit
|
||||
// for the Engine!
|
||||
if size as usize > context.engine().max_array_size()
|
||||
{
|
||||
return EvalAltResult::ErrorDataTooLarge(
|
||||
"Size to grow".to_string(),
|
||||
context.engine().max_array_size(),
|
||||
size as usize,
|
||||
Position::none(),
|
||||
).into();
|
||||
}
|
||||
|
||||
let array = Array::new();
|
||||
|
||||
for x in 0..size {
|
||||
array.push(x.into());
|
||||
}
|
||||
|
||||
OK(array.into())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
`#[export_module]` Parameters
|
||||
----------------------------
|
||||
|
||||
|
Reference in New Issue
Block a user