Build plugin that uses exports from dynamically linked core

Hey all, I'm trying to build a plugin system for my application and not having much succcess. I have a core library that contains structs, implementations, functions and macros that contains most of the logic for the application. This core is consumed by multiple clients such as a Tauri desktop application and a CLI. I also have a plugin that includes the core as a dependency by referencing its file path, and has crate-type = ["dylib"] in its Cargo.toml. Currently I am able to build the plugin, load it into the core with libloading, and call functions in the plugin. However, I have noticed that the entire core library is being included in the plugin's dylib, since it's a regular cargo dependency, and thus the core is being loaded into memory multiple times. Instead, I would like the plugin to include all of its dependencies except for the core, and then when the plugin is loaded by libloading, it uses the structs, functions etc. from the already loaded & running core to do whatever it needs to do. I've done some research and experimenting with different crate types and adding the -C relocation-model=pic rust flag, but have had no success.

If I was doing this in C, I'd create a header file with an outline of the core functionality, link to this header in the plugin, load the plugin at runtime and then the plugin would reference the symbols from the header already loaded into memory, without bringing its own build of the core with it. Obviously Rust doesn't have header files, so this is a bit trickier, and I'm not sure how to go about it.

I'm aware that building a plugin system like this could be error prone because of ABI differences across Rust versions, I would just like to do it as a proof of concept since I think I can standardise the rustc version I use in CI. Thanks for any help!

Having done weird Rust-C interop before, I would make the "core" look like it's written in C. Write that header file you mentioned. You can use cbindgen for that.

Once that is done, you can use bindgen to create the Rust external imports in your plugins.

It seems silly, I know. But in my experience, that is the way to get compatibility, make sure your tools make the right assumptions, and avoid lots of problems.

Good luck, and happy new year!

2 Likes