如何定义可以使用同一 crate 中的符号的宏

How to define a macro that can use symbols from the same crate

提问人:pr0gramista 提问时间:11/4/2023 最后编辑:cafce25pr0gramista 更新时间:11/4/2023 访问量:52

问:

我正在尝试创建自己的宏,其行为几乎与宏相似,但我想获得自己的结构,而不是获得一个。json!serde::Value

我使用以下代码成功了一半,但宏不能在此文件之外使用,因为它显示“在此范围内找不到类型”或“在此范围内找不到宏”等错误。Personjson

use serde_derive::{Deserialize, Serialize};
use serde_json::json;

mod utils;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
}

#[macro_export]
macro_rules! person_parse {
    ($json:tt) => {
        serde_json::from_value::<Person>(json!($json)).unwrap()
    };
}

fn main() {
    let john: Person = person_parse!({
        "name": "John Doe",
        "age": 43,
    });

    println!("{:?}", john);
}

评论


答:

4赞 pr0gramista 11/4/2023 #1

宏扩展为普通代码,因此,如果未导入名称,则在使用该名称的文件中找不到该名称。您可以导入 Person 结构体和 json!宏,但这有点不符合人体工程学。但是,您可以在宏中使用完全限定的名称,这样您就不需要添加导入。

#[macro_export]
macro_rules! person_parse {
    ($json:tt) => {
        serde_json::from_value::<$crate::Person>(serde_json::json!($json)).unwrap()
    };
}

在这里,我们使用了一个$crate元变量,它指的是当前的 crate,我们在宏使用之前添加了它。serde_json::json!

您可以在此处了解有关宏的更多信息:https://doc.rust-lang.org/reference/macros-by-example.html

评论

2赞 cafce25 11/4/2023
另一种方法是在宏中添加 。您可以使用短名称,并且用户不需要在范围内具有符号。use $crate::Person;