Hi all.

I want to develop a plugin system within my program, and I have a trait that functions defined by plugins should implement.

Currently, my code gets all the functions in a HashMap and then calls them by their name. Problem is, I have to create that hashmap myself by inserting every function myself.

I would really appreciate it if there was a way to say, suppose, all pub members of mod functions:: that implement this trait PluginFunction call register(hashmap) function. So as I add more functions as mod in functions it’ll be automatically added on compile.

Pseudocode:

Files:

src/
├── attrs.rs
├── functions
│   ├── attrs.rs
│   ├── export.rs
│   └── render.rs
├── functions.rs
├── lib.rs

Basically, in mod functions I want:

impl AllFunctions{
    pub fn new() -> Self {
       let mut functions_map = HashMap::new();[[
       register_all!(crate::functions::* implementing PluginFunction, &mut functions_map);
       Self { function_map }
  }
}

Right now I’m doing:

impl AllFunctions{
    pub fn new() -> Self {
       let mut functions_map = HashMap::new();[[
       crate::functions::attrs::PrintAttr{}.register(&mut functions_map);
       crate::functions::export::ExportCSV{}.register(&mut functions_map);
       crate::functions::render::RenderText{}.register(&mut functions_map);
       // More as I add more functions
       Self { function_map }
  }
}
  • @thevoidzeroOP
    link
    26 days ago

    Thank you for your detailed response.

    I am ok using macros. But even proc macro only get the tokens and using in on the whole mod is unstable unless you use use it on mod sth{...} instead of code being on in a different file (sth.rs).

    The plug-in system is dynamic in a sense that my plans for it are loading them through shared libraries (.dll, .so) compiled separately by users. But I also have internally provided core plugins that come with the program. But rust ABI system is not that stable, so in worst case I might have to ask users to just add plugin code to some directory and re-compile program instead of loading from shared libraries. That’s why I’m trying to make it as simple as possible. Asking users to modify the rust code somewhere else yo register the plugin might be met with resistance.

    I was thinking that using build script to parse the source code and generating those codes could work, but that seemed hacky. So I was trying to see if there are better solutions, as it felt like a problem people might have come across themselves.