1

I'm planning on making a game in Rust, and I'd like to have native plugins/mods in the form of dynamic libraries. I'm planning on using libloading for this.

Mods will be able to add new entities and items based on the existing game framework; I haven't worked out any specifics yet, but they should either use the game's traits on new structs, or construct existing structs using new stats, textures, etc.

The problem I'm facing is figuring out how to "export" the game's structs and implementations for mods/libraries to use, without compiling the mod along with the entire game.
For structs I'd like to expose to mods, I could probably throw together a minimal "header file" for my game and use it in each mod, but duplicating the actual code for each plugin seems very inefficient. Ideally, mods would use the game's native functions for common things like interacting with the world or displaying a GUI.

In libloading you can export symbols from a library to the main program, but I haven't heard of things working the other way around, even though it seems like it would be a fairly important feature to me. I've tried doing some research but I don't know what keywords to use, or even if this type of thing has a specific name.

Not being particularly experienced with Rust, I've only thought of 2 ways forward: either pass loaded libraries callbacks so they can use native functions, but I'm not sure how it'd work with structs, and I'm sure it'd get complicated quick; or I could give up on libraries and use a Lua as a modding interface, but at that point I might as well make all of the game's content in Lua.

Thanks!

6
  • 1
    I would recommend reading blog series A Plugin System in Rust. It is very in-depth, and should help you getting a broader picture on this topic. Commented Oct 30, 2023 at 5:44
  • 1
    @AleksanderKrauze Thanks for the link, it was pretty eye-opening. It didn't exactly cover my use case but I'm starting to see it'd be pretty hard to do in Rust, maybe just embedding a scripting language will save me a lot of pain... Commented Oct 30, 2023 at 7:37
  • 1
    You can call an init() function and pass it a pointer to struct to your game's functions. The plugin can save it and use them later. You can also expand your API in future versions and be backwards-compatible if you only add methods at the end of the struct (and the struct of course is #[repr(C)]). Probably also good to pass an API version number. Commented Oct 30, 2023 at 9:10
  • @ChayimFriedman That's definitely an option for a basic API, but let's say I have 20 struct types and each has 20 impl methods - that API struct would get out of hand very fast... I know what I'm asking for is probably unrealistic, but ideally I'd like to find a way to compile a library which uses types that are not actually included in said library. Maybe it's only possible by cutting up the library later, but as long as it can be automated, I'm open to almost any duct-tape solution Commented Nov 3, 2023 at 5:07
  • Is the problem the hand-writing of all API functions? I believe you can have a macro that does that. Commented Nov 3, 2023 at 5:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.