Create a Custom Package

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.

def_package!

def_package!(root:package_name:description, variable, block)

where:

ParameterDescription
rootroot namespace, usually rhai
package_namename of the package, usually ending in ...Package
descriptiondoc-comment for the package
variablea variable name holding a reference to the module (&mut Module) that is to form the package
blocka code block that initializes the package

Examples


#![allow(unused)]
fn main() {
// Import necessary types and traits.
use rhai::{
    def_package,            // 'def_package!' macro
    packages::Package,      // 'Package' trait
    packages::{             // pre-defined packages
        ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage
    }
};

// Define the package 'MyPackage'.
def_package!(rhai:MyPackage:"My own personal super package", module, {
    // Aggregate other packages simply by calling 'init' on each.
    ArithmeticPackage::init(module);
    LogicPackage::init(module);
    BasicArrayPackage::init(module);
    BasicMapPackage::init(module);

    // Register additional Rust functions using the standard 'set_fn_XXX' module API.
    let hash = module.set_fn_1("foo", |s: ImmutableString| {
        Ok(foo(s.into_owned()))
    });

    // Remember to update the parameter names/types and return type metadata.
    // 'set_fn_XXX' by default does not set function metadata.
    module.update_fn_metadata(hash, ["s: ImmutableString", "i64"]);
});
}

Create a Custom Package from a Plugin Module

By far the easiest way to create a custom module is to call plugin::combine_with_exported_module! from within def_package! which simply merges in all the functions defined within a plugin module.

In fact, this exactly is how Rhai’s built-in packages, such as BasicMathPackage, are implemented.

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.


#![allow(unused)]
fn main() {
// Import necessary types and traits.
use rhai::{
    def_package,
    packages::Package,
    packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage}
};
use rhai::plugin::*;

// Define plugin module.
#[export_module]
mod my_module {
    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'.
def_package!(rhai:MyPackage:"My own personal super package", module, {
    // Aggregate other packages simply by calling 'init' on each.
    ArithmeticPackage::init(module);
    LogicPackage::init(module);
    BasicArrayPackage::init(module);
    BasicMapPackage::init(module);

    // 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 (pulled up from 'my_sub_module')
    //
    combine_with_exported_module!(module, "my-functions", my_module));
});
}