wasmer
wasmer copied to clipboard
Question about my own imports and WASI using the C API
Summary
Couldn't find a mailing list, so this will have to do...
I have a C WASM module that exports some functions and imports one from the host. This is compiled as --target=wasm32-wasi
It's built against wasi-sysroot-20.0
I have a runtime using wasmtime and it all works fine. Trying to do this also with wasmer (4.0.0 from wasmer-linux-amd64.tar.gz) but am running into the following issue.
I guess I'm trying todo a combination of imports-exports.c & wasi.c
But I keep getting errors about either not finding the WASI import functions or the function I'm importing from the host.
E.g
$ ./wasi
Initializing...
Setting up WASI...
Loading binary...
Compiling module...
Instantiating module...
> Error instantiating module!
Error len: `139`
Error str: `Error while importing "wasi_snapshot_preview1"."proc_exit": unknown import. Expected Function(FunctionType { params: [I32], results: [] })`
# Change the order I'm doing things
$ ./wasi
Initializing...
Setting up WASI...
Loading binary...
Compiling module...
WASI version... 2 (SNAPSHOT0)
WASI imports... > Error getting WASI imports!
Error len: `47`
Error str: `Failed to resolve import "env" "imported_func"`
The first error is coming from wasm_instance_new()
the second from wasi_get_imports()
.
I just cannot find a way to appease both.
I've distilled this down to the following.
This runtime is based on the above two mentioned examples.
/*
* wasi.c
*
* Compile with
*
* gcc -Wall -Wextra -I../../wasmer-4.0.0/include -L../../wasmer-4.0.0/lib -o wasi wasi.c -lwasmer
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include "wasmer.h"
static wasm_trap_t *imported_func(const wasm_val_vec_t *args,
wasm_val_vec_t *results)
{
return NULL;
}
static void print_wasmer_error()
{
int error_len = wasmer_last_error_length();
if (error_len > 0) {
char *error_str = malloc(error_len);
printf("Error len: `%d`\n", error_len);
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);
free(error_str);
}
}
int main(void)
{
#ifndef WASMER_WASI_ENABLED
#error "No WASI support enabled in wasmer!"
#endif
wasm_engine_t *engine;
wasm_store_t *store;
wasm_module_t *module;
wasm_instance_t *instance;
wasm_functype_t *func_ty;
wasm_func_t *func;
wasm_extern_t *externs[1];
wasm_extern_vec_t imports;
wasm_byte_vec_t binary;
wasi_config_t *config;
wasi_env_t *wasi_env;
wasi_version_t wasi_ver;
bool get_imports_result;
FILE *file;
size_t file_size;
static const char * const wasi_versions[] = {
"INVALID_VERSION",
"LATEST",
"SNAPSHOT0",
"SNAPSHOT1",
"WASIX32V1",
"WASIX64V1",
};
printf("Initializing...\n");
engine = wasm_engine_new();
store = wasm_store_new(engine);
printf("Setting up WASI...\n");
config = wasi_config_new("example_program");
wasi_config_inherit_stdin(config);
wasi_config_inherit_stdout(config);
wasi_config_inherit_stderr(config);
printf("Loading binary...\n");
file = fopen("test.wasm", "r");
if (!file) {
printf("> Error loading module!\n");
return 1;
}
fseek(file, 0L, SEEK_END);
file_size = ftell(file);
fseek(file, 0L, SEEK_SET);
wasm_byte_vec_new_uninitialized(&binary, file_size);
if (fread(binary.data, file_size, 1, file) != 1) {
printf("> Error initializing module!\n");
return 1;
}
fclose(file);
printf("Compiling module...\n");
module = wasm_module_new(store, &binary);
if (!module) {
printf("> Error compiling module!\n");
return 1;
}
wasm_byte_vec_delete(&binary);
printf("Instantiating module...\n");
/* Export a function to the module */
func_ty = wasm_functype_new_0_0();
func = wasm_func_new(store, func_ty, imported_func);
wasm_functype_delete(func_ty);
*externs = (wasm_extern_t *){ wasm_func_as_extern(func) };
imports = (wasm_extern_vec_t)WASM_ARRAY_VEC(externs);
instance = wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
print_wasmer_error();
return 1;
}
wasi_env = wasi_env_new(store, config);
if (!wasi_env) {
printf("> Error building WASI env!\n");
print_wasmer_error();
return 1;
}
printf("WASI version... ");
wasi_ver = wasi_get_wasi_version(module);
printf("%d (%s)\n", wasi_ver, wasi_versions[wasi_ver]);
printf("WASI imports... ");
get_imports_result =
wasi_get_imports(store, wasi_env, module, &imports);
if (!get_imports_result) {
printf("> Error getting WASI imports!\n");
print_wasmer_error();
return 1;
}
if (!wasi_env_initialize_instance(wasi_env, store, instance)) {
printf("> Error initializing wasi env memory!\n");
print_wasmer_error();
return 1;
}
wasm_extern_vec_delete(&imports);
printf("Shutting down...\n");
wasi_env_delete(wasi_env);
wasm_module_delete(module);
wasm_instance_delete(instance);
wasm_store_delete(store);
wasm_engine_delete(engine);
printf("Done.\n");
return 0;
}
This is a basic WASM module loaded by the above.
/*
* test.c
*
* Compile with:
*
* clang -Wall -Wextra --target=wasm32-wasi --sysroot=../../wasi-sysroot -o test.wasm test.c
*/
#include <stdint.h>
typedef uint32_t u32;
typedef uint8_t u8;
__attribute__((import_module("env"), import_name("imported_func")))
void imported_func(void);
__attribute__((export_name("exported_func")))
int exported_func(u8 *addr, u32 mem_size)
{
imported_func();
return 0;
}
int main(void)
{
return 0;
}
The only reason for the main() function is to make wasi_get_wasi_version()
work, not that it's needed. Though I might have expected the reported version to be SNAPSHOT1 given the WASI functions are labelled as wasi_snapshot_preview1... (unless the '1' in SNAPSHOT is not related to the '1' in preview)...
Any pointers in the right direction would be appreciated. Hopefully I'm just missing something obvious...