...
This commit is contained in:
44
rhai_engine/rhaibook/rust/packages/builtin.md
Normal file
44
rhai_engine/rhaibook/rust/packages/builtin.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Built-In Packages
|
||||
=================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
`Engine::new` creates an [`Engine`] with the `StandardPackage` loaded.
|
||||
|
||||
`Engine::new_raw` creates an [`Engine`] with _no_ [package] loaded.
|
||||
|
||||
| Package | Description | In `Core` | In `Standard` |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | :-------: | :-----------: |
|
||||
| `LanguageCorePackage` | core functions for the Rhai language | yes | yes |
|
||||
| `ArithmeticPackage` | arithmetic operators (e.g. `+`, `-`, `*`, `/`) for numeric types that are not built in (e.g. `u16`) | yes | yes |
|
||||
| `BitFieldPackage` | basic [bit-field] functions | **no** | yes |
|
||||
| `BasicIteratorPackage` | numeric ranges (e.g. `range(1, 100, 5)`), iterators for [arrays], [strings], [bit-fields] and [object maps] | yes | yes |
|
||||
| `LogicPackage` | logical and comparison operators (e.g. `==`, `>`) for numeric types that are not built in (e.g. `u16`) | **no** | yes |
|
||||
| `BasicStringPackage` | basic string functions (e.g. `print`, `debug`, `len`) that are not built in | yes | yes |
|
||||
| `BasicTimePackage` | basic time functions (e.g. [timestamps], not available under [`no_time`] or [`no_std`]) | **no** | yes |
|
||||
| `MoreStringPackage` | additional string functions, including converting common types to string | **no** | yes |
|
||||
| `BasicMathPackage` | basic math functions (e.g. `sin`, `sqrt`) | **no** | yes |
|
||||
| `BasicArrayPackage` | basic [array] functions (not available under [`no_index`]) | **no** | yes |
|
||||
| `BasicBlobPackage` | basic [BLOB] functions (not available under [`no_index`]) | **no** | yes |
|
||||
| `BasicMapPackage` | basic [object map] functions (not available under [`no_object`]) | **no** | yes |
|
||||
| `BasicFnPackage` | basic methods for [function pointers] | yes | yes |
|
||||
| `DebuggingPackage` | basic functions for [debugging][debugger] (requires [`debugging`]) | yes | yes |
|
||||
| `CorePackage` | basic essentials | yes | yes |
|
||||
| `StandardPackage` | standard library (default for `Engine::new`) | **no** | yes |
|
||||
|
||||
|
||||
`CorePackage`
|
||||
-------------
|
||||
|
||||
If only minimal functionalities are required, register the `CorePackage` instead.
|
||||
|
||||
```rust
|
||||
use rhai::Engine;
|
||||
use rhai::packages::{Package, CorePackage};
|
||||
|
||||
let mut engine = Engine::new_raw();
|
||||
let package = CorePackage::new();
|
||||
|
||||
// Register the package into the 'Engine'.
|
||||
package.register_into_engine(&mut engine);
|
||||
```
|
69
rhai_engine/rhaibook/rust/packages/crate.md
Normal file
69
rhai_engine/rhaibook/rust/packages/crate.md
Normal file
@@ -0,0 +1,69 @@
|
||||
Create a Custom Package as an Independent Crate
|
||||
===============================================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
Creating a custom [package] as an independent crate allows it to be shared by multiple projects.
|
||||
|
||||
```admonish abstract.small "Key concepts"
|
||||
|
||||
* Create a Rust crate that specifies [`rhai`](https://crates.io/crates/rhai) as dependency.
|
||||
|
||||
* The main `lib.rs` module can contain the [package] being constructed.
|
||||
```
|
||||
|
||||
```admonish example.small
|
||||
The projects [`rhai-rand`] and [`rhai-sci`] show simple examples of creating a custom [package]
|
||||
as an independent crate.
|
||||
```
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
`Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "my-package" # 'my-package' crate
|
||||
|
||||
[dependencies]
|
||||
rhai = "{{version}}" # assuming {{version}} is the latest version
|
||||
```
|
||||
|
||||
`lib.rs`:
|
||||
|
||||
```rust
|
||||
use rhai::def_package;
|
||||
use rhai::plugin::*;
|
||||
|
||||
// This is a plugin module
|
||||
#[export_module]
|
||||
mod my_module {
|
||||
// Constants are ignored when used as a package
|
||||
pub const MY_NUMBER: i64 = 42;
|
||||
|
||||
pub fn greet(name: &str) -> String {
|
||||
format!("hello, {}!", name)
|
||||
}
|
||||
pub fn get_num() -> i64 {
|
||||
42
|
||||
}
|
||||
|
||||
// This is a sub-module, but if using combine_with_exported_module!, it will
|
||||
// be flattened and all functions registered at the top level.
|
||||
pub mod my_sub_module {
|
||||
pub fn get_sub_num() -> i64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define the package 'MyPackage' which is exported for the crate.
|
||||
def_package! {
|
||||
/// My own personal super package in a new crate!
|
||||
pub MyPackage(module) {
|
||||
combine_with_exported_module!(module, "my-functions", my_module);
|
||||
}
|
||||
}
|
||||
```
|
256
rhai_engine/rhaibook/rust/packages/create.md
Normal file
256
rhai_engine/rhaibook/rust/packages/create.md
Normal file
@@ -0,0 +1,256 @@
|
||||
Create a Custom Package
|
||||
=======================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
```admonish info.side "See also"
|
||||
|
||||
See also the [_One Engine Instance Per Call_]({{rootUrl}}/patterns/parallel.md) pattern.
|
||||
```
|
||||
|
||||
The macro `def_package!` can be used to create a custom [package].
|
||||
|
||||
A custom [package] can aggregate many other [packages] into a single self-contained unit.
|
||||
More functions can be added on top of others.
|
||||
|
||||
Custom [packages] are extremely useful when multiple [raw `Engine`] instances must be created such
|
||||
that they all share the same set of functions.
|
||||
|
||||
|
||||
`def_package!`
|
||||
--------------
|
||||
|
||||
> ```rust
|
||||
> def_package! {
|
||||
> /// Package description doc-comment
|
||||
> pub name(variable) {
|
||||
> :
|
||||
> // package init code block
|
||||
> :
|
||||
> }
|
||||
>
|
||||
> // Multiple packages can be defined at the same time,
|
||||
> // possibly with base packages and/or code to setup an Engine.
|
||||
>
|
||||
> /// Package description doc-comment
|
||||
> pub(crate) name(variable) : base_package_1, base_package_2, ... {
|
||||
> :
|
||||
> // package init code block
|
||||
> :
|
||||
> } |> |engine| {
|
||||
> :
|
||||
> // engine setup code block
|
||||
> :
|
||||
> }
|
||||
>
|
||||
> /// A private package description doc-comment
|
||||
> name(variable) {
|
||||
> :
|
||||
> // private package init code block
|
||||
> :
|
||||
> }
|
||||
>
|
||||
> :
|
||||
> }
|
||||
> ```
|
||||
|
||||
where:
|
||||
|
||||
| Element | Description |
|
||||
| :---------------------: | ---------------------------------------------------------------------------------------------------- |
|
||||
| description | doc-comment for the [package] |
|
||||
| `pub` etc. | visibility of the [package] |
|
||||
| name | name of the [package], usually ending in ...`Package` |
|
||||
| variable | a variable name holding a reference to the [module] forming the [package], usually `module` or `lib` |
|
||||
| base_package | an external [package] type that is merged into this [package] as a dependency |
|
||||
| package init code block | a code block that initializes the [package] |
|
||||
| engine | a variable name holding a mutable reference to an [`Engine`] |
|
||||
| engine setup code block | a code block that performs setup tasks on an [`Engine`] during registration |
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
```rust
|
||||
// Import necessary types and traits.
|
||||
use rhai::def_package; // 'def_package!' macro
|
||||
use rhai::packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage};
|
||||
use rhai::{FuncRegistration, CustomType, TypeBuilder};
|
||||
|
||||
/// This is a custom type.
|
||||
#[derive(Clone, CustomType)]
|
||||
struct TestStruct {
|
||||
foo: String,
|
||||
bar: i64,
|
||||
baz: bool
|
||||
}
|
||||
|
||||
def_package! {
|
||||
/// My own personal super package
|
||||
// Aggregate other base packages (if any) simply by listing them after a colon.
|
||||
pub MyPackage(module) : ArithmeticPackage, LogicPackage, BasicArrayPackage, BasicMapPackage
|
||||
{
|
||||
// Register additional Rust function.
|
||||
FuncRegistration::new("get_bar_value")
|
||||
.with_params_info(&["s: &mut TestStruct", "i64"])
|
||||
.set_into_module(module, |s: &mut TestStruct| s.bar);
|
||||
|
||||
// Register a function for use as a custom operator.
|
||||
FuncRegistration::new("@")
|
||||
.with_namespace(FnNamespace::Global) // <- make it available globally.
|
||||
.set_into_module(module, |x: i64, y: i64| x * x + y * y);
|
||||
} |> |engine| {
|
||||
// This optional block performs tasks on an 'Engine' instance,
|
||||
// e.g. register custom types and/or custom operators/syntax.
|
||||
|
||||
// Register custom type.
|
||||
engine.build_type::<TestStruct>();
|
||||
|
||||
// Define a custom operator '@' with precedence of 160
|
||||
// (i.e. between +|- and *|/).
|
||||
engine.register_custom_operator("@", 160).unwrap();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
~~~admonish tip.small "Tip: Feature gates on base packages"
|
||||
|
||||
Base packages in the list after the colon (`:`) can also have attributes (such as feature gates)!
|
||||
|
||||
```rust
|
||||
def_package! {
|
||||
// 'BasicArrayPackage' is used only under 'arrays' feature.
|
||||
pub MyPackage(module) :
|
||||
ArithmeticPackage,
|
||||
LogicPackage,
|
||||
#[cfg(feature = "arrays")]
|
||||
BasicArrayPackage
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
~~~
|
||||
|
||||
~~~admonish danger.small "Advanced: `Engine` setup with `|>`"
|
||||
|
||||
A second code block (in the syntax of a [closure]) following a right-triangle symbol (`|>`)
|
||||
is run whenever the [package] is being registered.
|
||||
|
||||
It allows performing setup tasks directly on that [`Engine`], e.g. registering [custom types],
|
||||
[custom operators] and/or [custom syntax].
|
||||
|
||||
```rust
|
||||
def_package! {
|
||||
pub MyPackage(module) {
|
||||
:
|
||||
:
|
||||
} |> |engine| {
|
||||
// Call methods on 'engine'
|
||||
}
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
|
||||
Create a Custom Package from a Plugin Module
|
||||
--------------------------------------------
|
||||
|
||||
```admonish question.side "Trivia"
|
||||
|
||||
This is exactly how Rhai's built-in [packages], such as `BasicMathPackage`, are actually implemented.
|
||||
```
|
||||
|
||||
By far the easiest way to create a custom [package] is to call `plugin::combine_with_exported_module!`
|
||||
from within `def_package!` which simply merges in all the functions defined within a [plugin module].
|
||||
|
||||
Due to specific requirements of a [package], `plugin::combine_with_exported_module!`
|
||||
_flattens_ all sub-modules (i.e. all functions and [type iterators] defined within sub-modules
|
||||
are pulled up to the top level instead) and so there will not be any sub-modules added to the [package].
|
||||
|
||||
Variables in the [plugin module] are ignored.
|
||||
|
||||
```rust
|
||||
// Import necessary types and traits.
|
||||
use rhai::def_package;
|
||||
use rhai::packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage};
|
||||
use rhai::plugin::*;
|
||||
|
||||
// Define plugin module.
|
||||
#[export_module]
|
||||
mod my_plugin_module {
|
||||
// Custom type.
|
||||
pub type ABC = TestStruct;
|
||||
|
||||
// Public constant.
|
||||
pub const MY_NUMBER: i64 = 42;
|
||||
|
||||
// Public function.
|
||||
pub fn greet(name: &str) -> String {
|
||||
format!("hello, {}!", name)
|
||||
}
|
||||
|
||||
// Non-public functions are by default not exported.
|
||||
fn get_private_num() -> i64 {
|
||||
42
|
||||
}
|
||||
|
||||
// Public function.
|
||||
pub fn get_num() -> i64 {
|
||||
get_private_num()
|
||||
}
|
||||
|
||||
// Custom operator.
|
||||
#[rhai_fn(name = "@")]
|
||||
pub fn square_add(x: i64, y: i64) -> i64 {
|
||||
x * x + y * y
|
||||
}
|
||||
|
||||
// A sub-module. If using 'combine_with_exported_module!', however,
|
||||
// it will be flattened and all functions registered at the top level.
|
||||
//
|
||||
// Because of this flattening, sub-modules are very convenient for
|
||||
// putting feature gates onto large groups of functions.
|
||||
#[cfg(feature = "sub-num-feature")]
|
||||
pub mod my_sub_module {
|
||||
// Only available under 'sub-num-feature'.
|
||||
pub fn get_sub_num() -> i64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def_package! {
|
||||
/// My own personal super package
|
||||
// Aggregate other base packages (if any) simply by listing them after a colon.
|
||||
pub MyPackage(module) : ArithmeticPackage, LogicPackage, BasicArrayPackage, BasicMapPackage
|
||||
{
|
||||
// Merge all registered functions and constants from the plugin module
|
||||
// into the custom package.
|
||||
//
|
||||
// The sub-module 'my_sub_module' is flattened and its functions
|
||||
// registered at the top level.
|
||||
//
|
||||
// The text string name in the second parameter can be anything
|
||||
// and is reserved for future use; it is recommended to be an
|
||||
// ID string that uniquely identifies the plugin module.
|
||||
//
|
||||
// The constant variable, 'MY_NUMBER', is ignored.
|
||||
//
|
||||
// This call ends up registering three functions at the top level of
|
||||
// the package:
|
||||
// 1) 'greet'
|
||||
// 2) 'get_num'
|
||||
// 3) 'get_sub_num' (flattened from 'my_sub_module')
|
||||
//
|
||||
combine_with_exported_module!(module, "my-mod", my_plugin_module));
|
||||
} |> |engine| {
|
||||
// This optional block is used to set up an 'Engine' during registration.
|
||||
|
||||
// Define a custom operator '@' with precedence of 160
|
||||
// (i.e. between +|- and *|/).
|
||||
engine.register_custom_operator("@", 160).unwrap();
|
||||
}
|
||||
}
|
||||
```
|
60
rhai_engine/rhaibook/rust/packages/index.md
Normal file
60
rhai_engine/rhaibook/rust/packages/index.md
Normal file
@@ -0,0 +1,60 @@
|
||||
Packages
|
||||
========
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
The built-in library of Rhai is provided as various _packages_ that can be turned into _shared_
|
||||
[modules], which in turn can be registered into the _global namespace_ of an [`Engine`] via
|
||||
`Engine::register_global_module`.
|
||||
|
||||
Packages reside under `rhai::packages::*` and the trait `rhai::packages::Package` must be loaded in
|
||||
order for packages to be used.
|
||||
|
||||
```admonish question.small "Trivia: Packages _are_ modules!"
|
||||
|
||||
Internally, a _package_ is a [module], with some conveniences to make it easier to define and use as
|
||||
a standard _library_ for an [`Engine`].
|
||||
|
||||
Packages typically contain Rust functions that are callable within a Rhai script.
|
||||
All _top-level_ functions in a package are available under the _global namespace_
|
||||
(i.e. they're available without namespace qualifiers).
|
||||
|
||||
Sub-[modules] and [variables] are ignored in packages.
|
||||
```
|
||||
|
||||
|
||||
Share a Package Among Multiple `Engine`'s
|
||||
-----------------------------------------
|
||||
|
||||
`Engine::register_global_module` and `Engine::register_static_module` both require _shared_ [modules].
|
||||
|
||||
Once a package is created (e.g. via `Package::new`), it can be registered into multiple instances of
|
||||
[`Engine`], even across threads (under the [`sync`] feature).
|
||||
|
||||
```admonish tip.small "Tip: Sharing package"
|
||||
|
||||
A package only has to be created _once_ and essentially shared among multiple [`Engine`] instances.
|
||||
|
||||
This is particularly useful when spawning large number of [raw `Engine`'s][raw `Engine`].
|
||||
```
|
||||
|
||||
```rust
|
||||
use rhai::Engine;
|
||||
use rhai::packages::Package // load the 'Package' trait to use packages
|
||||
use rhai::packages::CorePackage; // the 'core' package contains basic functionalities (e.g. arithmetic)
|
||||
|
||||
// Create a package - can be shared among multiple 'Engine' instances
|
||||
let package = CorePackage::new();
|
||||
|
||||
let mut engines_collection: Vec<Engine> = Vec::new();
|
||||
|
||||
// Create 100 'raw' Engines
|
||||
for _ in 0..100 {
|
||||
let mut engine = Engine::new_raw();
|
||||
|
||||
// Register the package into the global namespace.
|
||||
package.register_into_engine(&mut engine);
|
||||
|
||||
engines_collection.push(engine);
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user