标签: rust-macros

如何跨模块文件使用宏?

我在同一个包中的两个模块中有两个模块,其中包已macro_rules启用.我想在另一个模块中使用一个模块中定义的宏.

// macros.rs
#[macro_export] // or not? is ineffectual for this, afaik
macro_rules! my_macro(...)

// something.rs
use macros;
// use macros::my_macro; <-- unresolved import (for obvious reasons)
my_macro!() // <-- how?
Run Code Online (Sandbox Code Playgroud)

我目前遇到编译器错误" macro undefined: 'my_macro'"...这是有道理的; 宏系统在模块系统之前运行.我该如何解决这个问题?

module rust rust-macros

59
推荐指数
5
解决办法
2万
查看次数

如何编写自定义派生宏?

我正在尝试在 Rust 中编写我自己的派生模式宏,并且它的文档在示例中有些缺乏。

我有一个像这样的结构:

#[derive(MyMacroHere)]
struct Example {
    id: i64,
    value: Option<String>,
}
Run Code Online (Sandbox Code Playgroud)

我希望我的宏生成一个方法 à la

fn set_fields(&mut self, id: i64, value: Option<String>) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

使用TokenStream特征来实现类似目标的基本步骤是什么?

rust rust-macros

20
推荐指数
1
解决办法
6993
查看次数

如何以编程方式获取结构的字段数?

我有一个自定义结构,如下所示:

struct MyStruct {
    first_field: i32,
    second_field: String,
    third_field: u16,
}
Run Code Online (Sandbox Code Playgroud)

是否有可能以编程方式获取结构字段的数量(例如,通过方法调用field_count()):

let my_struct = MyStruct::new(10, "second_field", 4);
let field_count = my_struct.field_count(); // Expecting to get 3
Run Code Online (Sandbox Code Playgroud)

对于这个结构:

struct MyStruct2 {
    first_field: i32,
}
Run Code Online (Sandbox Code Playgroud)

......以下电话应该返回1:

let my_struct_2 = MyStruct2::new(7);
let field_count = my_struct2.field_count(); // Expecting to get count 1
Run Code Online (Sandbox Code Playgroud)

有没有像这样的API field_count()或者只能通过宏获得它?

如果使用宏可以实现这一点,那么应该如何实现?

struct rust rust-macros rust-proc-macros

20
推荐指数
2
解决办法
1886
查看次数

tt元变量类型在Rust宏中意味着什么?

我正在读一本关于Rust的书,并开始玩Rust宏.所有元变量类型都在那里解释并有示例,除了最后一个 - tt.根据这本书,它是一个"单一的标记树".我很好奇,它是什么,它用于什么?你能举个例子吗?

macros metaprogramming rust rust-macros

17
推荐指数
1
解决办法
2649
查看次数

有没有办法用宏来计算?

我想创建一个指定次数打印"Hello"的宏.它的使用方式如下:

many_greetings!(3);  // expands to three `println!("Hello");` statements
Run Code Online (Sandbox Code Playgroud)

创建该宏的天真方式是:

macro_rules! many_greetings {
    ($times:expr) => {{
        println!("Hello");
        many_greetings!($times - 1);
    }};
    (0) => ();
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为编译器不计算表达式; $times - 1不计算,但作为一个新的表达式输入宏.

macros rust rust-macros

14
推荐指数
3
解决办法
2112
查看次数

什么是内置`#[main]`属性?

我一直#[tokio::main]在我的一个程序中使用该宏。不合格的导入使用后main,遇到了意想不到的错误。

use tokio::main;

#[main]
async fn main() {}
Run Code Online (Sandbox Code Playgroud)
error[E0659]: `main` is ambiguous
 --> src/main.rs:3:3
  |
3 | #[main]
  |   ^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `main` could refer to a built-in attribute
Run Code Online (Sandbox Code Playgroud)

我一直在搜索文档,但找不到#[main]任何地方描述的这个内置属性。Rust 参考包含内置属性的索引。该索引不包含#[main],但它包含名为 的属性#[no_main]

我对存储库进行了搜索rustlang/rust,发现了一些似乎相关的代码,但它似乎使用了一对名为#[start]和 的宏#[rustc_main],而没有提及其#[main]本身。(这两个宏似乎都不能在稳定版上使用,会#[start]发出一个错误,表明它不稳定,并#[rustc_main]发出一个错误,表明它仅供编译器内部使用。)

我从名称中猜测它是为了将不同的函数标记为入口点而不是main,但它似乎也没有这样做:

error[E0659]: …
Run Code Online (Sandbox Code Playgroud)

program-entry-point entry-point rust rust-macros

14
推荐指数
1
解决办法
1169
查看次数

我该如何调试宏?

所以我有以下宏代码我正在尝试调试.我是从Rust Book的"The Deep end"一节中读到的.我重命名宏中的变量,以更密切地关注这篇文章.

我的目标是让程序打印出BCT程序的每一行.我很清楚这是编译器很重.

rustc给我的唯一错误是:

user@debian:~/rust/macros$ rustc --pretty expanded src/main.rs -Z unstable-options > src/main.precomp.rs
src/main.rs:151:34: 151:35 error: no rules expected the token `0`
src/main.rs:151     bct!(0, 1, 1, 1, 0, 0, 0; 1, 0);
Run Code Online (Sandbox Code Playgroud)

我可以采取什么步骤,以找出其中的宏观问题是从哪里来的?

这是我的代码:

fn main() {
{
    // "Bitwise Cyclic Tag" automation through macros
    macro_rules! bct {
        // cmd 0:  0 ... => ...
        (0, $($program:tt),* ; $_head:tt)
            => (bct_p!($($program),*, 0 ; ));
        (0, $($program:tt),* ; $_head:tt, $($tail:tt),*)
            => …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

11
推荐指数
2
解决办法
6494
查看次数

如何用零填充数组?

fn main() {
    let arr: [u8;8] = [97, 112, 112, 108, 101];
    println!("Len is {}",arr.len());
    println!("Elements are {:?}",arr);
}
Run Code Online (Sandbox Code Playgroud)
fn main() {
    let arr: [u8;8] = [97, 112, 112, 108, 101];
    println!("Len is {}",arr.len());
    println!("Elements are {:?}",arr);
}
Run Code Online (Sandbox Code Playgroud)

有什么办法可以用0来填充剩余的元素吗?就像是:

let arr: [u8;8] = [97, 112, 112, 108, 101].something();
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

11
推荐指数
3
解决办法
5549
查看次数

如何在不为每个字段重复“pub”的情况下创建一个所有字段都是公共的公共结构?

如何在 Rust 中定义一个公共结构,其中所有字段都是公共的,而不必pub在每个字段前重复修饰符?

一个pub_struct宏将是理想的:

pub_struct! Foo {
    a: i32,
    b: f64,
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这相当于:

pub struct Foo {
    pub a: i32,
    pub b: f64,
    //...
}
Run Code Online (Sandbox Code Playgroud)

struct public rust rust-macros

10
推荐指数
1
解决办法
5612
查看次数

如何通过Rust宏将表达式中的一个标识符替换为另一个标识符?

我正在尝试建立一个进行一些代码转换的宏,并且应该能够解析其自身的语法。这是我能想到的最简单的例子:

replace!(x, y, x * 100 + z) ~> y * 100 + z
Run Code Online (Sandbox Code Playgroud)

此宏应该能够用作为第三参数提供的表达式中的第二个标识符替换第一个标识符。宏应该对第三个参数的语言有所了解(在我的特定情况下,与示例相反,它不会在Rust中解析),并对其进行递归应用。

在Rust中构建此类宏的最有效方法是什么?我知道这种proc_macro方法和macro_rules!一种方法。但是我不确定是否macro_rules!足够强大来处理此问题,并且找不到如何使用来构建自己的转换的文档proc_macro。谁能指出我正确的方向?

rust rust-macros

10
推荐指数
1
解决办法
332
查看次数