Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix C API table/global/memory imports #227

Merged
merged 2 commits into from
Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 34 additions & 10 deletions lib/runtime-c-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,12 +454,24 @@ pub unsafe extern "C" fn wasmer_module_instantiate(
.or_insert_with(|| Namespace::new());

let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export,
wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export,
wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export,
wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export,
wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory;
Export::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Export;
(&*func_export).clone()
}
wasmer_import_export_kind::WASM_GLOBAL => {
let global = import.value.global as *mut Global;
Export::Global((&*global).clone())
}
wasmer_import_export_kind::WASM_TABLE => {
let table = import.value.table as *mut Table;
Export::Table((&*table).clone())
}
};
namespace.insert(import_name, unsafe { (&*export).clone() });
namespace.insert(import_name, export);
}
for (module_name, namespace) in namespaces.into_iter() {
import_object.register(module_name, namespace);
Expand Down Expand Up @@ -806,12 +818,24 @@ pub unsafe extern "C" fn wasmer_instantiate(
.or_insert_with(|| Namespace::new());

let export = match import.tag {
wasmer_import_export_kind::WASM_MEMORY => import.value.memory as *mut Export,
wasmer_import_export_kind::WASM_FUNCTION => import.value.func as *mut Export,
wasmer_import_export_kind::WASM_GLOBAL => import.value.global as *mut Export,
wasmer_import_export_kind::WASM_TABLE => import.value.table as *mut Export,
wasmer_import_export_kind::WASM_MEMORY => {
let mem = import.value.memory as *mut Memory;
Export::Memory((&*mem).clone())
}
wasmer_import_export_kind::WASM_FUNCTION => {
let func_export = import.value.func as *mut Export;
(&*func_export).clone()
}
wasmer_import_export_kind::WASM_GLOBAL => {
let global = import.value.global as *mut Global;
Export::Global((&*global).clone())
}
wasmer_import_export_kind::WASM_TABLE => {
let table = import.value.table as *mut Table;
Export::Table((&*table).clone())
}
};
namespace.insert(import_name, unsafe { (&*export).clone() });
namespace.insert(import_name, unsafe { export });
}
for (module_name, namespace) in namespaces.into_iter() {
import_object.register(module_name, namespace);
Expand Down
1 change: 1 addition & 0 deletions lib/runtime-c-api/tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ _deps
test-globals
test-exports
test-instantiate
test-imports
test-import-function
test-memory
test-module-imports
Expand Down
4 changes: 4 additions & 0 deletions lib/runtime-c-api/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required (VERSION 2.6)
project (WasmerCApiTests)

add_executable(test-imports test-imports.c)
add_executable(test-exports test-exports.c)
add_executable(test-globals test-globals.c)
add_executable(test-instantiate test-instantiate.c)
Expand All @@ -21,6 +22,8 @@ if(NOT WASMER_LIB)
message(FATAL_ERROR "wasmer library not found")
endif()

target_link_libraries(test-imports
general ${WASMER_LIB})
target_link_libraries(test-exports
general ${WASMER_LIB})
target_link_libraries(test-globals
Expand All @@ -43,6 +46,7 @@ target_link_libraries(test-tables
general ${WASMER_LIB})

enable_testing()
add_test(test-imports test-imports)
add_test(test-exports test-exports)
add_test(test-globals test-globals)
add_test(test-instantiate test-instantiate)
Expand Down
Binary file added lib/runtime-c-api/tests/hello_wasm.wasm
Binary file not shown.
154 changes: 154 additions & 0 deletions lib/runtime-c-api/tests/test-imports.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include <stdio.h>
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>

static print_str_called = false;

// Host function that will be imported into the Web Assembly Instance
void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len)
{
print_str_called = true;
wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0);
uint32_t mem_len = wasmer_memory_length(memory);
uint8_t *mem_bytes = wasmer_memory_data(memory);
printf("%.*s", len, mem_bytes + ptr);
}

// Use the last_error API to retrieve error messages
void print_wasmer_error()
{
int error_len = wasmer_last_error_length();
printf("Error len: `%d`\n", error_len);
char *error_str = malloc(error_len);
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);
}

int main()
{
// Create a new func to hold the parameter and signature
// of our `print_str` host function
wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32};
wasmer_value_tag returns_sig[] = {};
wasmer_import_func_t *func = wasmer_import_func_new(print_str, params_sig, 2, returns_sig, 0);

// Create module name for our imports
// represented in bytes for UTF-8 compatability
char *module_name = "env";
wasmer_byte_array module_name_bytes;
module_name_bytes.bytes = module_name;
module_name_bytes.bytes_len = strlen(module_name);

// Define a function import
char *import_name = "_print_str";
wasmer_byte_array import_name_bytes;
import_name_bytes.bytes = import_name;
import_name_bytes.bytes_len = strlen(import_name);
wasmer_import_t func_import;
func_import.module_name = module_name_bytes;
func_import.import_name = import_name_bytes;
func_import.tag = WASM_FUNCTION;
func_import.value.func = func;

// Define a memory import
char *import_memory_name = "memory";
wasmer_byte_array import_memory_name_bytes;
import_memory_name_bytes.bytes = import_memory_name;
import_memory_name_bytes.bytes_len = strlen(import_memory_name);
wasmer_import_t memory_import;
memory_import.module_name = module_name_bytes;
memory_import.import_name = import_memory_name_bytes;
memory_import.tag = WASM_MEMORY;
wasmer_memory_t *memory = NULL;
wasmer_limits_t descriptor;
descriptor.min = 256;
wasmer_limit_option_t max;
max.has_some = true;
max.some = 256;
descriptor.max = max;
wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor);
if (memory_result != WASMER_OK)
{
print_wasmer_error();
}
memory_import.value.memory = memory;

// Define a global import
char *import_global_name = "__memory_base";
wasmer_byte_array import_global_name_bytes;
import_global_name_bytes.bytes = import_global_name;
import_global_name_bytes.bytes_len = strlen(import_global_name);
wasmer_import_t global_import;
global_import.module_name = module_name_bytes;
global_import.import_name = import_global_name_bytes;
global_import.tag = WASM_GLOBAL;
wasmer_value_t val;
val.tag = WASM_I32;
val.value.I32 = 1024;
wasmer_global_t *global = wasmer_global_new(val, false);
global_import.value.global = global;

// Define a table import
char *import_table_name = "table";
wasmer_byte_array import_table_name_bytes;
import_table_name_bytes.bytes = import_table_name;
import_table_name_bytes.bytes_len = strlen(import_table_name);
wasmer_import_t table_import;
table_import.module_name = module_name_bytes;
table_import.import_name = import_table_name_bytes;
table_import.tag = WASM_TABLE;
wasmer_table_t *table = NULL;
wasmer_limits_t table_descriptor;
table_descriptor.min = 256;
wasmer_limit_option_t table_max;
table_max.has_some = true;
table_max.some = 256;
table_descriptor.max = table_max;
wasmer_result_t table_result = wasmer_table_new(&table, table_descriptor);
if (table_result != WASMER_OK)
{
print_wasmer_error();
}
table_import.value.table = table;

// Define an array containing our imports
wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import};

// Read the wasm file bytes
FILE *file = fopen("hello_wasm.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
fseek(file, 0, SEEK_SET);
fread(bytes, 1, len, file);
fclose(file);

// Creates a WebAssembly Instance from wasm bytes and imports
wasmer_instance_t *instance = NULL;
wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 3);
printf("Compile result: %d\n", compile_result);
if (compile_result != WASMER_OK)
{
print_wasmer_error();
}
assert(compile_result == WASMER_OK);

// Call the exported "hello_wasm" function of our instance
wasmer_value_t params[] = {};
wasmer_value_t result_one;
wasmer_value_t results[] = {result_one};
wasmer_result_t call_result = wasmer_instance_call(instance, "_hello_wasm", params, 0, results, 1);
printf("Call result: %d\n", call_result);
assert(call_result == WASMER_OK);
assert(print_str_called);

// Use *_destroy methods to cleanup as specified in the header documentation
wasmer_import_func_destroy(func);
wasmer_global_destroy(global);
wasmer_memory_destroy(memory);
wasmer_table_destroy(table);
wasmer_instance_destroy(instance);

return 0;
}