dlopen / libloading
This document ia a guide for setting the Rust application
up with Rust plugins that can be loaded dynamically
Additionally, these plugins can make calls to the
application’s public API, so that it can be invoked with same data structures and utilities for extending the
Rust has packed everything that you app needs to run inside of one executable.
So, by default, Rust will link all dependencies statically into the final executable.
Thus our plugins can’t use the functions and utilities in our application’s library.
In order to solve it, we should use
We should tell compiler to compile a dynamic library and a rust library.
Open and edit Cargo.toml to add following code:
dylib makes a
.so file that contain the machine code.
rlib makes a ‘.rlib’ file which is like a header file that provide rust with extra metadata. Without
.rlib, our application couldn’t know that which functions and utilities in the library.
Meanwhile we need to tell cargo to add some flags to the its rust compiler calls.
These settings go in a
Now, we create a new project named
plugin1 alongside the app project.
And add the following code in the
And insert another code in
Here we can edit
Cargo.toml to associate it to
app library. But the
app library would also re-compile, when we already have the app compiled. There is no reason to compile the app library twice.
So, here we specify
app as an external crate.
#[no_mangle] attribute on a function tells the compiler not to add any extra metadata to that symbol in the compiled output, and this allows us to call the function by name when we later load it into our app dynamically.
Now we attempt to
cargo build the crate but it will tells us that it can’t find the
app crate. This is we didn’t tell the cargo where is the
Therefor we should create a
build.rs script that can be used to do any kind of necessary setup to compile a library. In this case we just need to feed cargo some specially understood flags that tell it how to find our pre-compiled
Now we can run
cargo build and we will get a new
libplugin1.so file in our
Note: If you run cargo build and get an error like
error[E0464]: multiple matching crates for 'app', change directory to your app directory and run
cargo cleanfollowed by
This will get rid of any extra
rlibfile that may have been left over from when we first bulit our app as a standalone binnary.
After doing that you should be able to come back to your plugin and successfully run
cargo buildto build the library.
Now we can load the plugin into our app. To load plugins we are going to use the
[dlopen](https://crates.io/crates/dlopen) crate. The
dlopen crate will do the actual loading of the shared libraries and takes care of the lower level stuff so we don’t have to. Then, let’s add that crate to the
Cargo.toml for our app.
And update our app’s code. For example: