plug-in
Two days ago in the study of coco plug-in system, we often say to interface-oriented development rather than implementation-oriented, plug-in this thing, like the middleware in the back-end framework, we follow the framework defined interface to implement middleware, which can also be considered a plug-in, we have many mechanisms to achieve “Pre-compiler plug-in”, but like coco to compile and release the binary program, what is the way to allow users to define plug-ins to complement the functionality? You can’t just insert the user’s code during runtime and then recompile the whole program, right? Is there a way to load the user’s library files at runtime? Yes, this technique is called Dynamic Loading.
In coco with dlopen this crate implements dynamic loading, but in Rust dynamic loading seems to have to unsafe, just in the implementation of the plug-in mechanism for coco some moment, I suddenly had a new idea.
WebAssembly
WebAssembly is a new way of coding that runs in modern web browsers - it is a low-level assembly-like language with a compact binary format that can run with near-native performance and provides a compilation target for languages such as C / C ++ so that they can run on the web. It is also designed to coexist with JavaScript, allowing the two to work together. –MDN
WebAssembly was originally designed to run in the browser, but just like JS’s node, WebAssembly now has browser-independent runtimes such as wasmtime and wasmer, and they both provide helper libraries embedded in each major language, which means I can freely call functions in wasm binaries in the languages supported by this runtime? Try it!
wasmtime
I tried to make a demo with wasmtime, first creating a new crate.
|
|
Open the src/lib.rs
file and write a simple summation function.
no_mangle
tells the Rust compiler not to change the function name for subsequent calls. Also modify the Cargo.toml
file.
Then you can compile it with this command.
Now you can find the corresponding adder.wasm
file in the target directory under the project.
Next, create a crate: adders.wasm
.
|
|
In main.rs
, write the following code.
|
|
Don’t forget to introduce the wasmtime dependency, but running it now will report an error straight away.
|
|
After debugging, I found that the error was in the creation of the instance
, and browsing the documentation I found that if there are imports dependencies in wasm, then the third argument here cannot be an empty array, but an array of all dependencies, but where did such a simple function get the dependencies? The wasm file was converted to text format by the wasm2wat tool, then searched by grep, and sure enough, some dependencies were automatically added after compilation.
|
|
Because the target of our compilation is wasm32-wasi
, wasi is WebAssembly System Interface, a standardized WebAssembly system interface, and the code given by wasmtime in the section explaining how to use it in Rust is applicable to wasm32- unknown-unknown
(I have to say that the quality of the documentation is not very good), here if you change the compilation target to wasm32-unknown-unknown can be run directly.
But not to change the compilation target will have to slightly modify the program, according to the search issue, I changed the code.
|
|
Wasmtime currently supports five languages, wasmer supports more, so users can write plugins in C/C++ or Go, and we can call them in Rust programs and don’t have to write unsafe.
Summary
With WebAssembly we can call libraries written in other languages in Rust and vice versa, WebAssembly becomes an intermediate language or virtual machine, e.g. in Python, due to the dynamic typing feature, it can be used like this
I am very optimistic about the future of WebAssembly, the emergence of a standalone runtime, making WebAssembly a general public language runtime that implements “Run any code on any client”.