Generating functions in macros

I'm trying to write a macro that generates a function. The macro looks like this:

macro_rules! gen_interrupt_fn {
    ($i:ident, $p:path) => {
extern "x86-interrupt" fn handle_$i(_stack_frame: &mut InterruptStackFrame) {
    if let Some(tbl) = IRQ_FUNCS.try_read() {
        for func in tbl.get($p.convert_to_u8()).unwrap().iter() {
            (func)();
        }
    }
    signal_eoi($p.convert_to_u8());
}
}
}

Is this even a good idea? Rust gives me the following error when attempting to expand it:

error: expected one of `(` or `<`, found `cascade`
   --> src\interrupts.rs:624:34
    |
624 | extern "x86-interrupt" fn handle_$i(_stack_frame: &mut InterruptStackFrame) {
    |                                  ^^ expected one of `(` or `<`
...
752 | gen_interrupt_fn!(cascade, InterruptType::Cascade);
    | --------------------------------------------------- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

I was originally just going to have Python generate all of these, but I thought about using Rusts macro system to make the code a lot cleaner and easier to read. Have I written the macro wrong? I'm invoking it like so:

gen_interrupt_fn!(cascade, InterruptType::Cascade);

Any thoughts?

You can not concatenate an ident within a macro easily.
The easy way out is to move the 'handle_' into the call:

macro_rules! gen_interrupt_fn {
    ($i:ident, $p:path) => {
extern "x86-interrupt" fn $i(_stack_frame: &mut InterruptStackFrame) {
    if let Some(tbl) = IRQ_FUNCS.try_read() {
        for func in tbl.get($p.convert_to_u8()).unwrap().iter() {
            (func)();
        }
    }
    signal_eoi($p.convert_to_u8());
}
}
}

and then change the call to

gen_interrupt_fn!(handle_cascade, InterruptType::Cascade);

There are two other things that might work - concat_ident in the nightly and paste. But I had no luck with either.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.