Is there any way to use marco to define a complex struct?

Hi, I have a C library and I want to dynamically load it in a Rust program.
I have some function pointer definitions in C and I converted them into Rust:

pub type ptr_func1 = unsafe extern "C" fn(
    arg1: type1,
    arg2: type2,
) -> result1;

then I use a struct to store there all pointers and write some helper functions to call these function pointers without parentheses:

pub struct FuncPointers {
    func1: ptr_func1
}

impl FuncPointers {
    pub fn func1(&self, arg1: type1, arg2: type2) -> result1 {
        let ptr = self.func1;
        unsafe { ptr(arg1, arg2) }
    }
}

However there are more than 100 functions and finally code becomes ugly. Is it possible to define this struct with marcos?

Thanks.

Something like this?

use paste::paste;

macro_rules! func_pointers {
    ($v:vis $name:ident {$($f:ident($($arg_name:ident : $arg_ty:ty),* $(,)?) $(-> $res:ty)?),* $(,)?}) => {
        paste!{
        $(
            // using types such as PtrFunc1 here
            // to get snake_case, e.g. ptr_func1, use [<ptr_ $f>]
            $v type [<Ptr $f:camel>] = unsafe extern "C" fn($($arg_name: $arg_ty),*) $(-> $res)?;
        )*
            $v struct $name {
        $(
                $f: [<Ptr $f:camel>],
        )*
            }
            
            impl $name {
        $(
                pub fn $f(&self, $($arg_name: $arg_ty),*) $(-> $res)? {
                    let ptr = self.$f;
                    unsafe { ptr($($arg_name),*) }
                }
        )*
            }
        }
    }
}


// example usage
pub struct Type1;
pub struct Type2;
pub struct Type3;
pub struct Result1;

func_pointers!{
    pub FuncPointers {
        func1(arg1: Type1, arg2: Type2) -> Result1,
        func2(arg: Type3),
    }
}

(as a playground)

(paste is this crate.)

1 Like

It works! Thank you! :grinning: