17个不稳定版本 (3个破坏性更新)

0.4.0 2024年7月4日
0.2.1 2024年2月5日
0.1.12 2023年11月1日
0.1.9 2023年6月26日
0.1.4 2022年11月23日

#92 in 嵌入式开发

Download history 163/week @ 2024-04-13 262/week @ 2024-04-20 136/week @ 2024-04-27 16/week @ 2024-05-04 423/week @ 2024-05-11 98/week @ 2024-05-18 139/week @ 2024-05-25 323/week @ 2024-06-01 106/week @ 2024-06-08 224/week @ 2024-06-15 233/week @ 2024-06-22 263/week @ 2024-06-29 178/week @ 2024-07-06 110/week @ 2024-07-13 2/week @ 2024-07-20 42/week @ 2024-07-27

每月375次下载
4 个crates中使用(通过 vsmtp-rule-engine

MIT/Apache

22KB
282

Rhai Dylib

此crate提供了一个简单的API,用于在Rhai引擎中使用Rhai模块加载Rust的dylibcrate。您可以使用cargo-generate此模板Rhai生成自己的库项目。

加载器

Loader是一个trait,用于构建从内存中动态库加载rhai模块的对象。有一个libloading实现,它允许您通过cdylibdylibrust crate加载模块。

查看simple示例以获取更多详细信息。

模块解析器

此crate还提供了一个Rhai模块解析器,它可以在给定的路径加载动态库。

use rhai_dylib::module_resolvers::libloading::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 "/usr/lib/libmy" as my; // Import your dynamic library.

my::my_function(); // Use exported items !
"#).expect("failed to run script");

查看module_resolver示例以获取更多详细信息。

陷阱

此实现存在多个限制。

TL;DR 要使用此crate,您需要

  • 在同一个或没有工作区的空间内编译 所有内容,插件和将加载它们的程序。
  • 在使用您构建插件和将要加载它们的程序时,请使用与四个u64数组相同的rhai::config::hashing::set_hashing_seed函数。(例如:rhai::config::hashing::set_hashing_seed(Some([1, 2, 3, 4])))

TypeId

Rust TypeId 是一个用于编译时比较类型的对象。Rhai使用这些对象来检查一个 Dynamic 对象的类型。这对于动态库来说是个问题,因为 TypeIds 有时会在不同的编译之间发生变化。

这意味着在某些情况下,即使类型相同,Rhai也无法比较两种类型,因为插件和二进制文件中所述类型的 TypeId 不同。

为了解决这个问题,您需要在同一工作空间内编译您的主二进制文件和插件,或者在外部编译所有内容。例如,在一个工作空间内编译一个二进制文件,而在外部编译一个插件,可能会导致 TypeIds 不匹配。

您可以使用

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

在您的二进制文件和插件中检查类型ID值。

如果您有任何关于编译器如何在工作空间之间和单个crates之间生成这些typeids的想法,请帮助我们完善这份readme!

哈希

Rhai在底层使用 ahash crate 来创建函数调用的标识符。对于您的代码的每次编译,在哈希类型时会生成一个新的种子。因此,不同时间编译您的主程序和插件会导致哈希不匹配,这意味着您将无法调用插件的API。

为了绕过这个问题,您需要使用一个包含四个 u64 的数组的 rhai::config::hashing::set_hashing_seed 函数。

其他

如果您在阅读上述部分后插件仍然无法正常工作,您也可以检查以下点

  • 为所有crates使用相同的工具链版本。
  • 在所有crates中使用相同的rhai-dylib依赖版本。
  • 尝试以相同的目标类型构建crates。(都是调试或都是发布)
  • 为所有crates启用/禁用链接时间优化标志(-C lto)。

如果上述所有解决方案都不起作用,请不要犹豫,提出一个issue!

Rust ABI

您还可以使用Rust ABI实现一个插件,这是不稳定的,并且将在不同的编译器版本之间发生变化。

这意味着您将在主程序中使用的所有插件都需要使用相同的编译器版本编译。

依赖项

~3.5–9MB
~82K SLoC