wasm-micro-runtime/samples/wasm-c-api-imports/host/example1.c
liang.he 3698f2279b
Improve wasm-c-api instantiation-time linking (#1902)
Add APIs to help prepare the imports for the wasm-c-api `wasm_instance_new`:
- wasm_importtype_is_linked
- wasm_runtime_is_import_func_linked
- wasm_runtime_is_import_global_linked
- wasm_extern_new_empty

For wasm-c-api, developer may use `wasm_module_imports` to get the import
types info, check whether an import func/global is linked with the above API,
and ignore the linking of an import func/global with `wasm_extern_new_empty`.

Sample `wasm-c-api-import` is added and document is updated.
2023-02-13 15:06:04 +08:00

204 lines
5.4 KiB
C

/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdlib.h>
#include <stdio.h>
#include "wasm_c_api.h"
#include "wasm_export.h"
static wasm_trap_t *
host_logs(const wasm_val_vec_t *args, wasm_val_vec_t *results)
{
return NULL;
}
static bool
build_imports(wasm_store_t *store, const wasm_module_t *module,
wasm_extern_vec_t *out)
{
wasm_importtype_vec_t importtypes = { 0 };
wasm_module_imports(module, &importtypes);
wasm_extern_t *externs[32] = { 0 };
for (unsigned i = 0; i < importtypes.num_elems; i++) {
wasm_importtype_t *importtype = importtypes.data[i];
/* use wasm_extern_new_empty() to create a placeholder */
if (wasm_importtype_is_linked(importtype)) {
externs[i] = wasm_extern_new_empty(
store, wasm_externtype_kind(wasm_importtype_type(importtype)));
continue;
}
const wasm_name_t *module_name =
wasm_importtype_module(importtypes.data[i]);
const wasm_name_t *field_name =
wasm_importtype_name(importtypes.data[i]);
if (strncmp(module_name->data, "env", strlen("env")) == 0
&& strncmp(field_name->data, "log", strlen("log")) == 0) {
wasm_functype_t *log_type = wasm_functype_new_2_0(
wasm_valtype_new_i64(), wasm_valtype_new_i32());
wasm_func_t *log_func = wasm_func_new(store, log_type, host_logs);
wasm_functype_delete(log_type);
externs[i] = wasm_func_as_extern(log_func);
}
}
wasm_extern_vec_new(out, importtypes.num_elems, externs);
wasm_importtype_vec_delete(&importtypes);
return true;
}
int
main()
{
int main_ret = EXIT_FAILURE;
// Initialize.
printf("Initializing...\n");
wasm_engine_t *engine = wasm_engine_new();
if (!engine)
goto quit;
wasm_store_t *store = wasm_store_new(engine);
if (!store)
goto delete_engine;
// Load binary.
printf("Loading binary...\n");
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
FILE *file = fopen("send_recv.aot", "rb");
printf("> Load .aot\n");
#else
FILE *file = fopen("send_recv.wasm", "rb");
printf("> Load .wasm\n");
#endif
if (!file) {
printf("> Error loading module!\n");
goto delete_store;
}
int ret = fseek(file, 0L, SEEK_END);
if (ret == -1) {
printf("> Error loading module!\n");
goto close_file;
}
long file_size = ftell(file);
if (file_size == -1) {
printf("> Error loading module!\n");
goto close_file;
}
ret = fseek(file, 0L, SEEK_SET);
if (ret == -1) {
printf("> Error loading module!\n");
goto close_file;
}
wasm_byte_vec_t binary;
wasm_byte_vec_new_uninitialized(&binary, file_size);
if (fread(binary.data, file_size, 1, file) != 1) {
printf("> Error loading module!\n");
goto delete_binary;
}
// Compile.
printf("Compiling module...\n");
wasm_module_t *module = wasm_module_new(store, &binary);
if (!module) {
printf("> Error compiling module!\n");
goto delete_binary;
}
// Set Wasi Context
const char *addr_pool[1] = { "127.0.0.1" };
wasm_runtime_set_wasi_addr_pool(*module, addr_pool, 1);
// Instantiate.
printf("Instantiating module...\n");
wasm_extern_vec_t imports = { 0 };
ret = build_imports(store, module, &imports);
if (!ret) {
printf("> Error building imports!\n");
goto delete_module;
}
wasm_instance_t *instance =
wasm_instance_new(store, module, &imports, NULL);
if (!instance) {
printf("> Error instantiating module!\n");
goto delete_imports;
}
// Extract export.
printf("Extracting export...\n");
wasm_extern_vec_t exports;
wasm_instance_exports(instance, &exports);
if (exports.size == 0) {
printf("> Error accessing exports!\n");
goto delete_instance;
}
/**
* should use information from wasm_module_exports to avoid hard coding "1"
*/
const wasm_func_t *start_func = wasm_extern_as_func(exports.data[1]);
if (start_func == NULL) {
printf("> Error accessing export!\n");
goto delete_exports;
}
// Call. "_start(nil) -> i32"
printf("Calling _start ...\n");
wasm_val_t rs[1] = { WASM_I32_VAL(0) };
wasm_val_vec_t args = WASM_EMPTY_VEC;
wasm_val_vec_t results = WASM_ARRAY_VEC(rs);
wasm_trap_t *trap = wasm_func_call(start_func, &args, &results);
if (trap) {
wasm_name_t message = { 0 };
wasm_trap_message(trap, &message);
printf("> Error calling function! %s\n", message.data);
wasm_name_delete(&message);
wasm_trap_delete(trap);
goto delete_exports;
}
// Print result.
printf("Printing result...\n");
printf("> %u\n", rs[0].of.i32);
// Shut down.
printf("Shutting down...\n");
// All done.
printf("Done.\n");
main_ret = EXIT_SUCCESS;
delete_exports:
wasm_extern_vec_delete(&exports);
delete_instance:
wasm_instance_delete(instance);
delete_imports:
wasm_extern_vec_delete(&imports);
delete_module:
wasm_module_delete(module);
delete_binary:
wasm_byte_vec_delete(&binary);
close_file:
fclose(file);
delete_store:
wasm_store_delete(store);
delete_engine:
wasm_engine_delete(engine);
quit:
return main_ret;
}