首页 > 解决方案 > 如何将从配置文件加载的参数传递给程序宏函数?

问题描述

这是我试图解决的一个问题。我有多个生成预计算值表的过程宏函数。目前,我的程序宏函数采用文字整数形式的参数。我希望能够从配置文件中传递这些参数。我可以重写我的函数来从宏本身加载参数。但是,我想保留来自顶级 crate 的配置,就像在这个例子中一样:

top-level-crate/
    config/
        params.yaml
    macro1-crate/
    macro2-crate/
     

由于宏函数的输入是语法标记而不是运行时值,因此我无法从顶级板条箱加载文件并传递参数。

    use macro1_crate::gen_table1;
    use macro2_crate::gen_table2;

    const TABLE1: [f32;100] = gen_table1!(500, 123, 499);
    const TABLE2: [f32;100] = gen_table2!(1, 3);

    fn main() {
       // use TABLE1 and TABLE2 to do further computation.
        
    }

我希望能够从这样的配置文件将参数传递给 gen_table1 和 gen_table2 :


    use macro1_crate::gen_table1;
    use macro2_crate::gen_table2;
   
    // Load values PARAM1, PARAM2, PARAM3, PARAM4, PARAM5

    const TABLE1: [f32;100] = gen_table1!(PARAM1, PARAM2, PARAM3);
    const TABLE2: [f32;100] = gen_table2!(PARAM4, PARAM5);

    fn main() {
       // use TABLE1 and TABLE2 to do further computation.
        
    }

明显的问题是 PARAM1、PARAM2、PARAM3、PARAM4、PARAM5 是运行时值,而 proc 宏依赖构建时间信息来生成表。

quote!我正在考虑的一个选项是创建另一个 proc 宏,专门用于将配置加载到使用令牌构建的某种数据结构中。然后将其输入宏。但是,这感觉很hackish,并且需要多次加载配置文件。此外,params 数据结构需要跨宏紧密耦合。代码可能如下所示:


    use macro1_crate::gen_table1;
    use macro2_crate::gen_table2;
   
    const TABLE1: [f32;100] = gen_table1!(myparams!());
    const TABLE2: [f32;100] = gen_table2!(myparams!());

    fn main() {
       // use TABLE1 and TABLE2 to do further computation.
        
    }

有任何改进或进一步的建议吗?

标签: rustrust-macros

解决方案


gen_table1!(myparams!());不起作用:宏不会像函数调用那样从内向外扩展。您的gen_table1宏将接收文字标记流myparams ! ()并且无法评估此宏,因此无法访问myparams.

现在,我只看到了一种真正的方法来做你想做的事:从文件中加载参数gen_table1and gen_table2,然后只传递包含参数的文件的文件名。例如:

const TABLE1: [f32; 100] = gen_table1!("../config/params.yaml");
const TABLE2: [f32; 100] = gen_table2!("../config/params.yaml");

当然,这可能会导致这两个宏中的代码重复。但这应该可以使用常用工具来解决:将该参数加载提取到一个函数中(如果两个宏都位于同一个 crate 中)或另一个实用程序 crate 中(如果两个宏位于不同 crate 中)。


您还不断提到术语“运行时值”。我认为您的意思是“一个常量值,而不是文字”,并且您指的是这样的东西:

const PARAM1: u32 = load_param!();
const TABLE1: [f32; 100] = gen_table1!(PARAM1); // <-- this does not work as expected!

因为在这里,您的宏再次接收文字标记流PARAM1,而不是所述参数的值。

所以是的,我认为这就是“运行时价值”的意思。当然,我现在对此没有更好的术语,但是“运行时值”具有误导性/错误性,因为该值在编译时可用。如果你在谈论一个实际的运行时值,即一个只有在编译完成后才能在运行时知道的值,那么就不可能做你想做的事。这是因为 proc 宏在编译时运行一次,而从不在运行时运行。


推荐阅读