Reputation: 589
I'm just getting going with Rust, and am trying to smooth over a couple inconveniences using macros. The first is that the derive Defaults macros don't support const functions so they don't support static objects. For this, I got help and adapted this macro I was given, it works well:
#[macro_export]
macro_rules! define_struct_with_const_defaults {
($v:vis struct $name:ident { $($f_name:ident: $f_type:ty = $f_default:expr),* $(,)? }) => {
#[derive(Clone,Copy)]
$v struct $name {
$(
$f_name: $f_type,
)*
}
impl $name {
pub const fn new() -> $name {
$name {
$(
$f_name: $f_default,
)*
}
}
}
}
}
So the next thing I wanted to do was get painless structure access for unit testing with python going. So I thought I could do something like this:
use pyo3::prelude::*;
#[macro_export]
macro_rules! define_struct_with_const_defaults {
($v:vis struct $name:ident { $($f_name:ident: $f_type:ty = $f_default:expr),* $(,)? }) => {
#[derive(Clone,Copy)]
#[pyclass]
$v struct $name {
$(
#[pyo3(get, set)] $f_name: $f_type,
)*
}
impl $name {
pub const fn new() -> $name {
$name {
$(
$f_name: $f_default,
)*
}
}
}
}
}
But that doesn't work, the complaint is "cannot find attribute pyclass
in this scope"
On the other hand, if I do this, it works:
use pyo3::prelude::*;
#[pyclass]
struct bar {
baz: i32,
}
This is beyond my level of understanding. It seems to be related to nesting macros, I'm wondering whether it has something to do with order of evaluation.
Eventually, I'd like to conditionally compile the pyo3 stuff with a config macro, depending on whether I'm in a unit test environment, but I can't even get this far ...
Any help would be appreciated in understanding what is going on here.
Upvotes: 0
Views: 460
Reputation: 27186
The problem is probably that the macro will insert #[pyclass]
at the callsite of it. So you have to put your use pyo3::prelude::*;
there or even better include the full path in the macro to avoid name conflicts:
#[macro_export]
macro_rules! define_struct_with_const_defaults {
($v:vis struct $name:ident { $($f_name:ident: $f_type:ty = $f_default:expr),* $(,)? }) => {
#[derive(Clone,Copy)]
#[::pyo3::prelude::pyclass]
$v struct $name {
$(
#[pyo3(get, set)] $f_name: $f_type,
)*
}
impl $name {
pub const fn new() -> $name {
$name {
$(
$f_name: $f_default,
)*
}
}
}
}
}
Upvotes: 1