33 个版本
0.3.15 | 2024年1月26日 |
---|---|
0.3.14 | 2023年12月21日 |
0.3.13 | 2023年11月1日 |
0.3.11 | 2023年7月23日 |
0.0.1 | 2015年7月22日 |
#72 在 Rust 模式
686,776 每月下载量
用于 842 个crate (102 直接)
21KB
198 行
类型化分布式插件注册
该crate提供了一种方法来设置插件注册表,插件可以从任何链接到您的应用程序的源文件中注册。不需要有一个所有插件的中心列表。
[dependencies]
inventory = "0.3"
支持 rustc 1.62+
示例
假设我们正在编写一个命令行标志库,并希望允许应用程序中的任何源文件注册与其相关的命令行标志。
这是由gflags使用的标志注册方式,与维护单个中心标志列表相比,更适合大规模开发,因为中心列表将成为由数千名开发人员同时开发的应用程序中无穷无尽的合并冲突来源。
实例化插件注册表
让我们使用一个 struct Flag
作为插件类型,它将包含标志的短名称,如 -v
,全名称如 --verbose
,以及可能的其他信息,如参数类型和帮助文本。我们使用 inventory::collect!
调用来实例化插件注册表。
pub struct Flag {
short: char,
name: &'static str,
/* ... */
}
impl Flag {
pub const fn new(short: char, name: &'static str) -> Self {
Flag { short, name }
}
}
inventory::collect!(Flag);
这个 collect!
调用必须在定义插件类型的同一crate中。此宏不“执行”任何操作,所以将其放置在任何函数体之外。
注册插件
现在,任何具有对 Flag
类型访问权限的crate都可以将标志注册为插件。插件可以由声明插件类型的同一crate注册,也可以由任何下游crate注册。
inventory::submit! {
Flag::new('v', "verbose")
}
submit!
宏并不“运行”任何内容,因此请将其放置在任何函数体之外。特别是请注意,所有链接到您的应用程序的所有源文件中的 submit!
调用都同时生效。一个 submit!
调用不是一个需要从 main
调用的语句以执行。
遍历插件
值 inventory::iter::<T>
是一个元素类型为 &'static T
的迭代器,遍历所有注册的类型为 T
的插件。
for flag in inventory::iter::<Flag> {
println!("-{}, --{}", flag.short, flag.name);
}
迭代器遍历相同类型插件的顺序没有保证。它们可以以任何顺序访问。
工作原理
库存建立在类似于 C 中的 __attribute__((constructor))
的运行时初始化函数之上,类似于 ctor
crate。每次对 inventory::submit!
的调用都会产生一个垫片,该垫片评估给定的表达式并将其注册到其对应类型的注册表中。这种注册作为静态链接元素的 life-before-main 的一部分动态发生。动态加载的库中的元素在 dlopen 发生时注册。
平台支持包括 Linux、macOS、iOS、FreeBSD、Android、Windows 以及少数其他平台。除此之外,其他平台将发现没有注册任何插件。
有关不涉及 life-before-main 的插件注册的不同方法的详细信息,请参阅 linkme
crate。
许可证
根据您的选择,受Apache 许可证 2.0 版或MIT 许可证的许可。除非您明确说明,否则根据 Apache-2.0 许可证的定义,您提交的任何有意提交以包含在此软件包中的贡献,将按照上述方式双许可,不附加任何其他条款或条件。