A plugin system for the Rhai embedded scripting language.

Overview

Rhai Dylib

This crate exposes a simple API to load dylib Rust crates in a Rhai engine using Rhai modules.

🚧 This is a work in progress, the API is subject to change. Please do make recommendations on what you want it to be via issues, discussions or pull requests !

Loader

Loader is a trait that is used to build objects that load rhai modules from dynamic libraries in memory. A libloading implementation is available, which enables you to load modules via a cdylib or dylib rust crate.

Check the simple example for more details.

You can easily setup a dynamic library for Rhai by using cargo-generate and the rhai-dylib-template.

Module Resolver

This crate also expose a Rhai Module Resolver that loads dynamic libraries at the given path.

use rhai_dylib::DylibModuleResolver;

let mut engine = rhai::Engine::new();

// use `rhai::module_resolvers::ModuleResolversCollection` if you need to resolve using
// other resolvers.
// Check out https://docs.rs/rhai/latest/rhai/module_resolvers/struct.ModuleResolversCollection.html
engine.set_module_resolver(DylibModuleResolver::new());

engine.run(r#"
// import your dynamic library.
import "path/to/my/dylib";

// ...
"#).expect("failed to run script");

Check the module_resolver example for more details.

Pitfalls

There are multiple limitations with this implementation.

TL;DR To use this crate, you need to:

  • Compile EVERYTHING, plugins and program that will load them, inside the SAME workspace or WITHOUT a workspace.
  • Export the RHAI_AHASH_SEED environment variable with the SAME four u64 array (i.e. RHAI_AHASH_SEED="[1, 2, 3, 4]") when building your plugins and the program that will load them.

TypeId

Rust TypeId is an object used to compare types at compile time. Rhai uses those to check which type a Dynamic object is. This is a problem for dynamic libraries because TypeIds sometime change between compilations.

That means that in certain situations, Rhai cannot compare two types, even tough they are the same, because the TypeId of said types is different between the plugin and the binary.

To fix this, you will need to compile your main binary AND plugins inside the SAME workspace, or compile everything OUTSIDE of a workspace. Compiling, for example, a binary in a workspace, and a plugin outside will probably result in TypeIds mismatch.

You can use

println!("{:?}", std::any::TypeId::of::<rhai::Map>());

In your binary & plugins to check the type id value.

If you have any idea of how the compiler generates those typeids between workspaces and single crates, please help us complete this readme !

Hashing

Rhai uses the ahash crate under the hood to create identifiers for function calls. For each compilation of your code, a new seed is generated when hashing the types. Therefore, compiling your main program and your plugin different times will result in a hash mismatch, meaning that you won't be able to call the API of your plugin.

To bypass that, you need to inject the RHAI_AHASH_SEED environment variable with an array of four u64.

export RHAI_AHASH_SEED="[1, 2, 3, 4]" # The seed is now fixed and won't change between compilations.

# Compiling will create the same hashes for functions.
cargo build --manifest-path ./my_program/Cargo.toml
cargo build --manifest-path ./my_plugin/Cargo.toml

instead of exporting the variable like above, you can use a cargo config file.

# .cargo/config.toml
[env]
# Replace the seed to your own liking, it must be the same for every plugins.
RHAI_AHASH_SEED = "[1, 2, 3, 4]"

Beware: the code handling the RHAI_AHASH_SEED environment variable is not yet merged into the main branch of Rhai. This crate uses a personal fork of schungx for the time being.

Rust ABI

You also can implement a plugin using the Rust ABI, which is unstable and will change between compiler versions.

This means that all of the plugins that you will use in your main program need to be compiled with the EXACT same compiler version.

TODO

Here is a list of stuff that we could implement or think about. (to move in issues)

  • How could we "restrain" the API access of the rhai engine ? Lock those behind features ? Using a new type that wraps the engine (Proxy) ?
  • Lock plugin loaders behind features.
  • Create macros that generate entry points.
  • Update seeds for ahash.
  • Add some unit & integration tests.
  • the "internals" feature is necessary for the impl of the module resolver. We should directly merge that into Rhai itself.
You might also like...
Simple low-level web server to serve file uploads with some shell scripting-friendly features

http_file_uploader Simple low-level web server to serve file uploads with some shell scripting-friendly features. A bridge between Web's multipart/for

A CLI app that exposes most of the h3o API for scripting.

h3o-cli — A CLI app exposing the h3o API for scripting How to install Pre-compiled binaries You can download a pre-compiled executable for Linux, MacO

Lapce plugin for the Php language.

lapce-php-intelephense Lapce plugin for the Php language. Prerequisites Install Intelephense, typically by running: $ npm i intelephense -g Settings S

First project in rust which will be to make an accounts system & Leaderboard/Score system

rust-backend this is my first project in rust which will be to make a backend for compsci project it will include: Accounts, Player Achievements (if I

Low-level Rust library for implementing terminal command line interface, like in embedded systems.

Terminal CLI Need to build an interactive command prompt, with commands, properties and with full autocomplete? This is for you. Example, output only

Source code for our paper
Source code for our paper "Higher-order finite elements for embedded simulation"

Higher-order Finite Elements for Embedded Simulation This repository contains the source code used to produce the results for our paper: Longva, A., L

A Rust command line tool to simplify embedded development and deployment.

Bobbin-CLI bobbin-cli is a tool designed to make it easy to build, deploy, test and debug embedded devices using a unified CLI. bobbin-cli understands

A text renderer for Rust's embedded-graphics crate, based on U8g2
A text renderer for Rust's embedded-graphics crate, based on U8g2

u8g2-fonts This crate is a pure Rust reimplementation of the font subsystem of U8g2. It is intended for the embedded-graphics ecosystem. Licensing Whi

Simple Secure Static (HTTPS) File Server with embedded certificate

Secure Static File Server Static Files HTTPs server with self signed embedded certificate Installation Install using cargo: cargo install ssfs Or buil

Comments
  • Use compile_error to prevent building unless under linux or windows.

    Use compile_error to prevent building unless under linux or windows.

    In lib.rs consider adding a line:

    #[cfg(not(target_os = "linux"))]
    #[cfg(not(target_os = "windows"))]
    compile_error!("unsupported platform - only Linux & Windows are supported");
    

    This way the crate won't build on o/s other than Linux and Windows.

    opened by schungx 3
  • Compilation error on Windows

    Compilation error on Windows

    https://github.com/rhaiscript/rhai-dylib/blob/main/src/plugin_loader/dylib.rs#L61 needs to be replaced by a feature gate, as if cfg!(...) will also try to compile the block (only to have it discarded via if false).

    bug 
    opened by schungx 1
Releases(v0.1.4)
Owner
Rhai - Embedded scripting language and engine for Rust
A small, fast, easy-to-use scripting language and evaluation engine that integrates tightly with Rust. Builds for most common targets including no-std and WASM.
Rhai - Embedded scripting language and engine for Rust
bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language

bevy_scriptum is a a plugin for Bevy that allows you to write some of your game logic in a scripting language. Currently, only Rhai is supported, but more languages may be added in the future.

Jarosław Konik 7 Jun 24, 2023
Scientific computing for Rhai.

About rhai-sci This crate provides some basic scientific computing utilities for the Rhai scripting language, inspired by languages like MATLAB, Octav

Rhai - Embedded scripting language and engine for Rust 5 Dec 5, 2022
Super-lightweight Immediate-mode Embedded GUI framework, based on the awesome embedded-graphics library. Written in Rust.

Kolibri - A GUI framework made to be as lightweight as its namesake What is Kolibri? Kolibri is an embedded Immediate Mode GUI mini-framework very str

null 6 Jun 24, 2023
A simple, human-friendly, embeddable scripting language

Mica Language reference · Rust API A simple, human-friendly scripting language, developed one feature at a time. Human-friendly syntax inspired by Rub

Mica programming language 32 Dec 30, 2022
The GameLisp scripting language

GameLisp GameLisp is a scripting language for Rust game development. To get started, take a look at the homepage. Please note that GameLisp currently

Fleabit 348 Nov 29, 2022
Open-source compiler for the Papyrus scripting language of Bethesda games.

Open Papyrus Compiler This project is still WORK IN PROGRESS. If you have any feature requests, head over to the Issues tab and describe your needs. Y

erri120 22 Dec 5, 2022
A safe, fast, lightweight embeddable scripting language written in Rust.

Bud (budlang) A safe, fast, lightweight embeddable scripting language written in Rust. WARNING: This crate is not anywhere near being ready to publish

Khonsu Labs 13 Dec 27, 2022
YAL is Yet Another scripting Language(but worse)

YAL - Yet Another Language YAL is yet another scripting language(but worse). Syntax Basic syntax fun main() { print("Hello, World!"); } Fibonacci

MD Gaziur Rahman Noor 16 Nov 14, 2022
Shell scripting that will knock your socks off

atom Shell scripting that will knock your socks off. NOTE: Click the image above for a video demonstration.

adam mcdaniel 256 Dec 14, 2022
A command line interface meant to bridge the gap between Rust and shell scripting

clawbang A command line interface meant to bridge the gap between Rust and shell scripting. Intended for use with HEREDOCs and shebangs: $ clawbang <<

Chris Dickinson 52 Mar 25, 2022