Rust宏属性扩展库cairo-lang-macro-attributes的使用,为Cairo语言提供自定义过程宏和编译时元编程支持

Cairo Lang Macro Attributes

通过cairo-lang-macro公开的Rust过程宏,作为Scarb过程宏的共享接口。

安装

在项目目录运行以下Cargo命令:

cargo add cairo-lang-macro-attributes

或在Cargo.toml中添加以下行:

cairo-lang-macro-attributes = "0.2.0"

使用示例

以下是一个完整的使用示例:

// 在Cargo.toml中声明依赖
// [dependencies]
// cairo-lang-macro-attributes = "0.2.0"

use cairo_lang_macro_attributes::derive_proc_macro;

// 派生宏定义
#[proc_macro_derive(SimpleDerive)]
pub fn simple_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // 实现派生逻辑
    input
}

// 属性宏定义  
#[proc_macro_attribute]
pub fn simple_attr(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // 实现属性逻辑
    item
}

// 使用示例
#[derive(SimpleDerive)]
struct MyStruct {
    field: i32,
}

#[simple_attr]
fn my_function() {
    // 函数体
}

完整示例

以下是更完整的示例代码,展示了如何实际使用这些宏:

// Cargo.toml 依赖
// [dependencies]
// cairo-lang-macro-attributes = "0.2.0"
// syn = { version = "2.0", features = ["full"] }
// quote = "1.0"

use cairo_lang_macro_attributes::derive_proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};

// 派生宏实现 - 为结构体生成默认实现
#[proc_macro_derive(DefaultStruct)]
pub fn default_struct_derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    
    // 生成默认实现
    let expanded = quote! {
        impl #name {
            pub fn default() -> Self {
                Self {
                    field: 0
                }
            }
        }
    };
    
    expanded.into()
}

// 属性宏实现 - 为函数添加日志功能
#[proc_macro_attribute]
pub fn log_func(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as syn::ItemFn);
    let fn_name = &input.sig.ident;
    
    // 添加日志打印
    let expanded = quote! {
        #input
        
        println!("Function {} called", stringify!(#fn_name));
    };
    
    expanded.into()
}

// 使用示例
#[derive(DefaultStruct)]
struct MyData {
    field: i32,
}

#[log_func]
fn process_data() {
    println!("Processing data...");
}

fn main() {
    let data = MyData::default();
    println!("Default field value: {}", data.field);
    
    process_data();
}

元数据

  • 版本: 0.2.0
  • 许可证: MIT
  • 类别: 开发工具
  • 大小: 4.07 KiB

所有者

  • StarkNet Crates.io Admins团队
  • maciektr个人用户

这个库为Cairo语言提供了编译时元编程支持,通过Rust的过程宏系统实现了自定义派生和属性宏的功能。


1 回复

Rust宏属性扩展库cairo-lang-macro-attributes的使用指南

cairo-lang-macro-attributes 是一个为Cairo语言提供自定义过程宏和编译时元编程支持的Rust库。它为Cairo开发者提供了强大的元编程能力,可以在编译时生成和转换代码。

主要功能

  1. 提供自定义属性宏支持
  2. 实现编译时代码生成
  3. 支持Cairo语言的元编程扩展
  4. 简化重复代码模式

安装方法

在Cargo.toml中添加依赖:

[dependencies]
cairo-lang-macro-attributes = "0.1.0"  # 请使用最新版本

完整示例demo

下面是一个完整的cairo-lang-macro-attributes使用示例,展示了如何创建自定义属性宏和派生宏:

// 首先创建一个新的库crate来存放过程宏
// cargo new my-macros --lib
// 在Cargo.toml中设置proc-macro = true

use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;

// 自定义属性宏示例
#[proc_macro_attribute]
pub fn log_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // 解析输入项
    let input = parse_macro_input!(item as syn::Item);
    
    // 生成新代码,在函数执行前后添加日志
    match input {
        syn::Item::Fn(mut func) => {
            let fn_name = &func.sig.ident;
            let fn_block = &func.block;
            
            // 修改函数体
            func.block = syn::parse_quote! {
                {
                    println!("[LOG] 开始执行函数: {}", stringify!(#fn_name));
                    let result = #fn_block;
                    println!("[LOG] 函数执行结束: {}", stringify!(#fn_name));
                    result
                }
            };
            
            // 返回修改后的TokenStream
            TokenStream::from(quote! { #func })
        }
        _ => {
            // 如果不是函数,原样返回
            TokenStream::from(quote! { #input })
        }
    }
}

// 派生宏示例
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // 解析输入
    let input = parse_macro_input!(input as DeriveInput);
    let name = input.ident;
    
    // 生成实现代码
    let expanded = quote! {
        impl #name {
            fn hello_macro() {
                println!("Hello, Macro! 我是 {}", stringify!(#name));
            }
        }
    };
    
    // 返回生成的代码
    TokenStream::from(expanded)
}

// Cairo合约相关宏示例
#[proc_macro_attribute]
pub fn generate_abi(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // 这里简化为只是添加一个标记
    let input = parse_macro_input!(item as syn::Item);
    
    let expanded = quote! {
        #input
        
        // 在实际应用中,这里会生成完整的ABI定义
        const _GENERATED_ABI: &str = "ABI生成占位符";
    };
    
    TokenStream::from(expanded)
}

使用这些宏的示例代码:

// 在另一个crate中使用这些宏
use my_macros::{log_attr, HelloMacro, generate_abi};

// 使用自定义属性宏
#[log_attr]
fn my_function(a: i32, b: i32) -> i32 {
    a + b
}

// 使用派生宏
#[derive(HelloMacro)]
struct MyStruct;

// Cairo合约示例
#[starknet::contract]
mod MyContract {
    #[generate_abi]
    impl MyContract {
        #[external]
        fn update_value(ref self: ContractState, new_value: felt252) {
            // 合约逻辑
        }
    }
}

fn main() {
    // 调用使用了属性宏的函数
    let result = my_function(1, 2);
    println!("结果: {}", result);
    
    // 调用派生宏生成的方法
    MyStruct::hello_macro();
}

注意事项

  1. 过程宏需要在单独的crate中定义,并在Cargo.toml中设置proc-macro = true
  2. 调试过程宏可以使用cargo expand命令查看宏展开后的代码
  3. 注意错误处理,可以使用syn::Error生成友好的编译错误
  4. 对于复杂的宏,建议使用synquote库来解析和生成代码
回到顶部