rust - 如何在编译时静态注册结构?

标签 rust

我正在寻找在编译时静态注册结构的正确方法。

这个要求的起源是有一堆小程序有专门的任务,这样如果我运行myprog foo,它会调用foo小程序。

所以我开始定义一个 Applet 结构:

struct Applet {
    name: &str,
    call: fn(),
}

然后我可以这样定义我的 foo applet:

fn foo_call() {
    println!("Foo");
}
let foo_applet = Applet { name: "foo", call: foo_call };

现在我想注册这个小程序,这样我的 main 函数就可以调用它了:

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    match AppletRegistry.get(args[1]) {
        Some(x) => x.call(),
        _ => (),
    }
}

整个交易是关于如何实现 AppletRegistry 以便我可以最好在编译时列出所有可用的 applet。

最佳答案

你不能。

Rust 的一个有意识的设计选择是“main 之前没有代码”,因此不支持这种事情。从根本上说,您需要在某处明确调用注册小程序的代码。

需要执行此类操作的 Rust 程序将明确列出所有可能的实现,并构造一个单一的静态数组。像这样:

pub const APPLETS: &'static [Applet] = [
    Applet { name: "foo", call: ::applets::foo::foo_call },
    Applet { name: "bar", call: ::applets::bar::bar_call },
];

(有时,重复的元素可以用宏来简化,在这个例子中,你可以改变它,让名字只被提及一次。)

理论上,您可以通过像 D 这样的语言在幕后执行的操作来实现它,但这将是特定于平台的,并且可能需要弄乱链接器脚本和/或修改编译器。

旁白:#[test] 呢? #[test] 很神奇,由编译器处理。简短的版本是:它的工作是在箱子中找到所有测试并构建所述巨型列表,然后测试运行器使用它有效地替换你的 main功能。不,您无法做任何类似的事情。

关于rust - 如何在编译时静态注册结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32678845/

相关文章:

asynchronous - 如何使用 tokio::join 有条件地运行两个函数之一?

rust - 如何在Yew应用程序中包括 sleep 功能?

rust - AssertUnwindSafe 如何与 CatchUnwind future 一起使用

recursion - 正确的 Rust 匹配习惯用法

rust - 使用 Trait 作为 Vec 类型

rust - 如何创建一个 Box<UnsafeCell<[T]>>

rust - 如何在 Rust 中查找两个字符串是否具有公共(public)字符

rust - 如何在 Rust 中以异步方式运行另一个函数?

generics - 如果我为 B 实现 From<A>,是否也会为 Vec<B> 实现 From<Vec<A>>?

rust - 有没有办法结合多个特征来定义新特征?