This patch does several things. 1. For the crate `wasmer-c-api`, the library name is modified from `wasmer_c_api` to `wasmer` in `Cargo.toml`. That way, the new library files are named `libwasmer.*` rather than `libwasmer_c_api.*`. That's the primaly goal of this patch. The rest is a consequence of this point. Why do we want that? Because the `build.rs` script of the `wasmer-c-api` crate will configure the `soname` (on Linux), the `install_name` + `current_version` + `compatibility_version` (on macOS), and the `out-implib` + `output-def` (on Windows) for a library named `libwasmer`, which is the name we provide in the Wasmer package for the Wasmer libraries. If we want everything to be testable, we cannot use `libwasmer` in `soname` for a file named `libwasmer_c_api` for example. If we rename the file when packaging (as it's done prior this patch), we would need to re-update all those information in the `Makefile`. It implies to duplicate the code in 2 places. So let's do things right directly and only once: We want the library to be named `libwasmer`, let's do that. 2. For the crate `wasmer-c-api`, since the library name has been renamed to `wasmer`, it creates a conflict with the `wasmer` crate which is a dependency. Consequently, this patch also updates the `Cargo.toml` file to modifiy the dependency name with the special `package` attribute (see https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml to learn more). So now, the `wasmer` refers to the `wasmer_c_api` crate, and `wasmer-api` refers to the `wasmer` crate. 3. The code of the `wasmer-c-api` crate is updated accordingly. The `WasmerEnv` derive procedural macro fails because it expects a crate named `wasmer` (which is now `wasmer_api`), so we implement the `WasmerEnv` trait by hand. 4. The patch updates the `build.rs` script of the `wasmer-c-api` crate: 1. In the `build_cdylib_link_arg` function: The dependency to the `cdylib-link-lines` crate has been removed because the output is not exactly the one we expect. So we compute all the `cargo:rustc-cdylib-link-arg=…` lines by hand. The version number no longer appears in the library file name for example. 2. In the `build_inline_c_env_vars` function: Values passed to `LDFLAGS` have been updated to be `libwasmer` rather than `libwasmer_c_api`. 3. A new `shared_object_dir` helper function has been created because it's used in `build_inline_c_env_vars` and in `build_cdylib_link_arg`. 5. The `Makefile` has been updated: 1. In `package-capi`, we no longer rename `libwasmer_c_api` to `libwasmer` since the name is correctly defined since the beginning now. Calling `install_name_tool` on macOS is no longer required since `install_name` is correctly set by the linker in the `build.rs` script of `wasmer-c-api`. 2. In `package-docs`, some stuffs have been fixed, like the `SOURCE_VERSION` variable that didn't exist, so removed, or the `mkdir` command that was incorrect etc. 3. In `build-docs`, the `wasmer-c-api` crate is excluded from the list of crates to generate the documentation for. Mostly because the `build-docs-capi` recipe exists, and we must use it to generate the documentation of `wasmer-c-api` now. 4. In `build-docs-capi`, we generate the documentation for the `wasmer-c-api` crate. But `rustdoc` uses the library name for the directory name in the `target/doc/` directory. Since the library name is now `wasmer`, it creates a conflict with the `wasmer` crate. Consequently, we update the library name by using `sed` on the `Cargo.toml` file before running `cargo doc`, to finally restore `Cargo.toml` as it was previously.
wasmer-c-api

This crate exposes a C and a C++ API for the Wasmer runtime. It also fully supports the wasm-c-api common API.
Usage
Once you install Wasmer in your system, the shared object files and the headers are available inside the Wasmer installed path.
$WASMER_DIR/
lib/
libwasmer.{so,dylib,dll}
include/
wasm.h
wasmer.h
wasmer.hh
wasmer.h
Wasmer binary also ships with wasmer-config
an utility tool that outputs config information needed to compile programs which use Wasmer.
The full C API documentation can be found here: https://wasmerio.github.io/wasmer/crates/wasmer_c_api/index.html
Here is a simple example to use the C API:
#include <stdio.h>
#include "wasmer.h"
int main(int argc, const char* argv[]) {
const char *wat_string =
"(module\n"
" (type $sum_t (func (param i32 i32) (result i32)))\n"
" (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32)\n"
" local.get $x\n"
" local.get $y\n"
" i32.add)\n"
" (export \"sum\" (func $sum_f)))";
wasm_byte_vec_t wat;
wasm_byte_vec_new(&wat, strlen(wat_string), wat_string);
wasm_byte_vec_t wasm_bytes;
wat2wasm(&wat, &wasm_bytes);
wasm_byte_vec_delete(&wat);
printf("Creating the store...\n");
wasm_engine_t* engine = wasm_engine_new();
wasm_store_t* store = wasm_store_new(engine);
printf("Compiling module...\n");
wasm_module_t* module = wasm_module_new(store, &wasm_bytes);
if (!module) {
printf("> Error compiling module!\n");
return 1;
}
wasm_byte_vec_delete(&wasm_bytes);
printf("Creating imports...\n");
wasm_extern_vec_t import_object = WASM_EMPTY_VEC;
printf("Instantiating module...\n");
wasm_instance_t* instance = wasm_instance_new(store, module, &import_object, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
return 1;
}
printf("Retrieving exports...\n");
wasm_extern_vec_t exports;
wasm_instance_exports(instance, &exports);
if (exports.size == 0) {
printf("> Error accessing exports!\n");
return 1;
}
printf("Retrieving the `sum` function...\n");
wasm_func_t* sum_func = wasm_extern_as_func(exports.data[0]);
if (sum_func == NULL) {
printf("> Failed to get the `sum` function!\n");
return 1;
}
printf("Calling `sum` function...\n");
wasm_val_t args_val[2] = { WASM_I32_VAL(3), WASM_I32_VAL(4) };
wasm_val_t results_val[1] = { WASM_INIT_VAL };
wasm_val_vec_t args = WASM_ARRAY_VEC(args_val);
wasm_val_vec_t results = WASM_ARRAY_VEC(results_val);
if (wasm_func_call(sum_func, &args, &results)) {
printf("> Error calling the `sum` function!\n");
return 1;
}
printf("Results of `sum`: %d\n", results_val[0].of.i32);
wasm_func_delete(sum_func);
wasm_module_delete(module);
wasm_extern_vec_delete(&exports);
wasm_instance_delete(instance);
wasm_store_delete(store);
wasm_engine_delete(engine);
}
Building
You can compile Wasmer shared library from source:
make build-capi
This will generate the shared library (depending on your system):
- Windows:
target/release/libwasmer_c_api.dll - macOS:
target/release/libwasmer_runtime_c_api.dylib - Linux:
target/release/libwasmer_runtime_c_api.so
If you want to generate the library and headers in a friendly format as shown in Usage, you can execute the following in Wasmer root:
make package-capi
This command will generate a package directory, that you can then use easily in the Wasmer C API examples.
Testing
Tests are run using the release build of the library. If you make changes or compile with non-default features, please ensure you rebuild in release mode for the tests to see the changes.
To run all the full suite of tests, enter Wasmer root directory and run the following commands:
$ make test-capi
wasmer config
wasmer config output various configuration information needed to compile programs which use Wasmer.
wasmer config --pkg-config
It outputs the necessary details for compiling and linking a program to Wasmer,
using the pkg-config format:
$ wasmer config --pkg-config > $PKG_CONFIG_PATH/wasmer.pc
wasmer config --includedir
Directory containing Wasmer headers:
$ wasmer config --includedir
/users/myuser/.wasmer/include
wasmer config --libdir
Directory containing Wasmer libraries:
$ wasmer config --libdir
/users/myuser/.wasmer/lib
wasmer config --libs
Libraries needed to link against Wasmer components:
$ wasmer config --libs
-L/Users/myuser/.wasmer/lib -lwasmer
wasmer config --libs
Libraries needed to link against Wasmer components:
$ wasmer config --cflags
-I/Users/myuser/.wasmer/include/wasmer
License
Wasmer is primarily distributed under the terms of the MIT license (LICENSE).