From 566154009790cc26a9faae4772dd262b9bdc0056 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 27 Mar 2019 09:42:56 +0100 Subject: [PATCH 1/4] chore(runtime-c-api) Move `.wasm` files into the `assets` directory. --- .../tests/{ => assets}/hello_wasm.wasm | Bin lib/runtime-c-api/tests/{ => assets}/sum.wasm | Bin .../tests/{ => assets}/wasm_sample_app.wasm | Bin lib/runtime-c-api/tests/test-exports.c | 2 +- lib/runtime-c-api/tests/test-import-function.c | 2 +- lib/runtime-c-api/tests/test-imports.c | 2 +- lib/runtime-c-api/tests/test-instantiate.c | 2 +- lib/runtime-c-api/tests/test-module-exports.c | 4 ++-- lib/runtime-c-api/tests/test-module-imports.c | 2 +- lib/runtime-c-api/tests/test-module-serialize.c | 2 +- lib/runtime-c-api/tests/test-module.c | 4 ++-- lib/runtime-c-api/tests/test-validate.c | 2 +- 12 files changed, 11 insertions(+), 11 deletions(-) rename lib/runtime-c-api/tests/{ => assets}/hello_wasm.wasm (100%) rename lib/runtime-c-api/tests/{ => assets}/sum.wasm (100%) rename lib/runtime-c-api/tests/{ => assets}/wasm_sample_app.wasm (100%) diff --git a/lib/runtime-c-api/tests/hello_wasm.wasm b/lib/runtime-c-api/tests/assets/hello_wasm.wasm similarity index 100% rename from lib/runtime-c-api/tests/hello_wasm.wasm rename to lib/runtime-c-api/tests/assets/hello_wasm.wasm diff --git a/lib/runtime-c-api/tests/sum.wasm b/lib/runtime-c-api/tests/assets/sum.wasm similarity index 100% rename from lib/runtime-c-api/tests/sum.wasm rename to lib/runtime-c-api/tests/assets/sum.wasm diff --git a/lib/runtime-c-api/tests/wasm_sample_app.wasm b/lib/runtime-c-api/tests/assets/wasm_sample_app.wasm similarity index 100% rename from lib/runtime-c-api/tests/wasm_sample_app.wasm rename to lib/runtime-c-api/tests/assets/wasm_sample_app.wasm diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index b282f1911a2..bb216bcd0cb 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-import-function.c b/lib/runtime-c-api/tests/test-import-function.c index ce6736deb31..92e3e821db7 100644 --- a/lib/runtime-c-api/tests/test-import-function.c +++ b/lib/runtime-c-api/tests/test-import-function.c @@ -57,7 +57,7 @@ int main() wasmer_import_t imports[] = {import}; // Read the wasm file bytes - FILE *file = fopen("wasm_sample_app.wasm", "r"); + FILE *file = fopen("assets/wasm_sample_app.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-imports.c b/lib/runtime-c-api/tests/test-imports.c index 9c0c45467c2..4713719ed03 100644 --- a/lib/runtime-c-api/tests/test-imports.c +++ b/lib/runtime-c-api/tests/test-imports.c @@ -117,7 +117,7 @@ int main() wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import}; // Read the wasm file bytes - FILE *file = fopen("hello_wasm.wasm", "r"); + FILE *file = fopen("assets/hello_wasm.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-instantiate.c b/lib/runtime-c-api/tests/test-instantiate.c index e7fae37e416..20332623ebb 100644 --- a/lib/runtime-c-api/tests/test-instantiate.c +++ b/lib/runtime-c-api/tests/test-instantiate.c @@ -7,7 +7,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-module-exports.c b/lib/runtime-c-api/tests/test-module-exports.c index 48fe6f25bce..f290ef45b36 100644 --- a/lib/runtime-c-api/tests/test-module-exports.c +++ b/lib/runtime-c-api/tests/test-module-exports.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); @@ -50,4 +50,4 @@ int main() printf("Destroy exports\n"); wasmer_export_descriptors_destroy(exports); return 0; -} \ No newline at end of file +} diff --git a/lib/runtime-c-api/tests/test-module-imports.c b/lib/runtime-c-api/tests/test-module-imports.c index b63d308f2c6..532005928fd 100644 --- a/lib/runtime-c-api/tests/test-module-imports.c +++ b/lib/runtime-c-api/tests/test-module-imports.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("wasm_sample_app.wasm", "r"); + FILE *file = fopen("assets/wasm_sample_app.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-module-serialize.c b/lib/runtime-c-api/tests/test-module-serialize.c index 6f6a918813f..b984186465c 100644 --- a/lib/runtime-c-api/tests/test-module-serialize.c +++ b/lib/runtime-c-api/tests/test-module-serialize.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); diff --git a/lib/runtime-c-api/tests/test-module.c b/lib/runtime-c-api/tests/test-module.c index 062caf5b8a2..a3f21f6a1f9 100644 --- a/lib/runtime-c-api/tests/test-module.c +++ b/lib/runtime-c-api/tests/test-module.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); @@ -48,4 +48,4 @@ int main() printf("Destroy module\n"); wasmer_module_destroy(module); return 0; -} \ No newline at end of file +} diff --git a/lib/runtime-c-api/tests/test-validate.c b/lib/runtime-c-api/tests/test-validate.c index 689cf50f29a..8ce135d8230 100644 --- a/lib/runtime-c-api/tests/test-validate.c +++ b/lib/runtime-c-api/tests/test-validate.c @@ -6,7 +6,7 @@ int main() { // Read the wasm file bytes - FILE *file = fopen("sum.wasm", "r"); + FILE *file = fopen("assets/sum.wasm", "r"); fseek(file, 0, SEEK_END); long len = ftell(file); uint8_t *bytes = malloc(len); From 6fca475564596049f2080a9cda48b8f1c1305e15 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 27 Mar 2019 10:44:47 +0100 Subject: [PATCH 2/4] feat(runtime-c-api) Implement the `wasmer_export_to_memory` function. This new function returns a `wasmer_memory_t` from a `wasmer_export_t`. --- lib/runtime-c-api/src/lib.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index e83d54bf37c..80774ce610e 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -2,7 +2,7 @@ extern crate wasmer_runtime; extern crate wasmer_runtime_core; use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t}; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::error::Error; use std::ffi::CStr; @@ -1409,6 +1409,34 @@ pub unsafe extern "C" fn wasmer_export_to_func( export as *const wasmer_export_func_t } +/// Gets a memory pointer from an export pointer. +/// +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_to_memory( + export: *const wasmer_export_t, + memory: *mut *mut wasmer_memory_t, +) -> wasmer_result_t { + let named_export = &*(export as *const NamedExport); + let export = &named_export.export; + + if let Export::Memory(exported_memory) = export { + *memory = exported_memory as *const Memory as *mut wasmer_memory_t; + wasmer_result_t::WASMER_OK + } else { + update_last_error(CApiError { + msg: "cannot cast the `wasmer_export_t` pointer to a `wasmer_memory_t` \ + pointer because it does not represent a memory export." + .to_string(), + }); + wasmer_result_t::WASMER_ERROR + } +} + /// Gets name from wasmer_export #[no_mangle] #[allow(clippy::cast_ptr_alignment)] @@ -1517,9 +1545,8 @@ pub extern "C" fn wasmer_instance_context_data_get( #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_memory_data(mem: *const wasmer_memory_t) -> *mut uint8_t { - let memory = mem as *const Memory; - use std::cell::Cell; - unsafe { ((*memory).view::()[..]).as_ptr() as *mut Cell as *mut u8 } + let memory = unsafe { &*(mem as *const Memory) }; + memory.view::()[..].as_ptr() as *mut Cell as *mut u8 } /// Gets the size in bytes of a Memory From 4d0312f0ed984fa7f804e6e7b8602fb5853c8b0c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 27 Mar 2019 10:49:28 +0100 Subject: [PATCH 3/4] test(runtime-c-api) New test suite for `wasmer_export_to_memory`. --- lib/runtime-c-api/tests/.gitignore | 1 + lib/runtime-c-api/tests/CMakeLists.txt | 5 ++ .../tests/assets/return_hello.rs | 4 + .../tests/assets/return_hello.wasm | Bin 0 -> 170 bytes .../tests/test-exported-memory.c | 73 ++++++++++++++++++ lib/runtime-c-api/tests/test-exports.c | 4 +- 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 lib/runtime-c-api/tests/assets/return_hello.rs create mode 100644 lib/runtime-c-api/tests/assets/return_hello.wasm create mode 100644 lib/runtime-c-api/tests/test-exported-memory.c diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index b8f6888c2a7..ed3b6ed6e92 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -10,6 +10,7 @@ compile_commands.json CTestTestfile.cmake _deps rust-build +test-exported-memory test-exports test-globals test-import-function diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 136c0c1e919..ef9804f019b 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required (VERSION 2.6) project (WasmerRuntimeCApiTests) +add_executable(test-exported-memory test-exported-memory.c) add_executable(test-exports test-exports.c) add_executable(test-globals test-globals.c) add_executable(test-import-function test-import-function.c) @@ -35,6 +36,10 @@ set( "/WX" > ) +target_link_libraries(test-exported-memory general ${WASMER_LIB}) +target_compile_options(test-exported-memory PRIVATE ${COMPILER_OPTIONS}) +add_test(test-exported-memory test-exported-memory) + target_link_libraries(test-exports general ${WASMER_LIB}) target_compile_options(test-exports PRIVATE ${COMPILER_OPTIONS}) add_test(test-exports test-exports) diff --git a/lib/runtime-c-api/tests/assets/return_hello.rs b/lib/runtime-c-api/tests/assets/return_hello.rs new file mode 100644 index 00000000000..39e77019348 --- /dev/null +++ b/lib/runtime-c-api/tests/assets/return_hello.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn return_hello() -> *const u8 { + b"Hello, World!\0"[..].as_ptr() +} diff --git a/lib/runtime-c-api/tests/assets/return_hello.wasm b/lib/runtime-c-api/tests/assets/return_hello.wasm new file mode 100644 index 0000000000000000000000000000000000000000..a7f79c376791b48cd3ac1857070a28452b2d8210 GIT binary patch literal 170 zcmXwyu?~VT7zV$eS_z;7i;0`=z66`2o8xbxHIkH;lrlKM6ZlL%nv&>rm)vkrLq`Be z(hW3;gs_s-6Oj~za$P19s@MER@n?FG>&|pOJQM7hTc_J#n#lLjHL>-MqpGbT6wD8! vdal)A1afArqGIE;piMAw4DQ>l^*~0*GfGj-%ct1U&$j2KpAJ_atUi7KKBg +#include "../wasmer.h" +#include +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("assets/return_hello.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); + + // Instantiate the module. + wasmer_import_t imports[] = {}; + wasmer_instance_t *instance = NULL; + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 0); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + // Call the `return_hello` function. + wasmer_value_t params[] = {}; + wasmer_value_t result; + wasmer_value_t results[] = {result}; + + wasmer_result_t call_result = wasmer_instance_call(instance, "return_hello", params, 0, results, 1); + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + assert(call_result == WASMER_OK); + assert(results[0].value.I32 == 1048576); + + // Get all exports. + wasmer_exports_t *exports = NULL; + wasmer_instance_exports(instance, &exports); + + int export_length = wasmer_exports_len(exports); + printf("exports_length: %d\n", export_length); + assert(export_length == 5); + + // Get the `memory` export. + wasmer_export_t *export = wasmer_exports_get(exports, 1); + wasmer_import_export_kind kind = wasmer_export_kind(export); + assert(kind == WASM_MEMORY); + + wasmer_byte_array export_name = wasmer_export_name(export); + printf("export_name: `%.*s`\n", export_name.bytes_len, export_name.bytes); + + // Cast the export into a memory. + wasmer_memory_t *memory; + wasmer_result_t export_to_memory_result = wasmer_export_to_memory(export, &memory); + printf("Export to memory result: %d\n", export_to_memory_result); + printf("Memory pointer: %p\n", memory); + assert(export_to_memory_result == WASMER_OK); + + uint32_t memory_length = wasmer_memory_length(memory); + assert(memory_length == 17); + + // Read the data from the memory. + uint8_t *memory_data = wasmer_memory_data(memory); + uint8_t *returned_string = memory_data + results[0].value.I32; + + printf("Returned string from Wasm: %s\n", returned_string); + assert(strcmp("Hello, World!", (const char *) returned_string) == 0); + + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + + return 0; +} diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index bb216bcd0cb..951c4f3a4d2 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -17,14 +17,14 @@ int main() wasmer_import_t imports[] = {}; wasmer_instance_t *instance = NULL; wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 0); - printf("Compile result: %d\n", compile_result); + printf("Compile result: %d\n", compile_result); assert(compile_result == WASMER_OK); wasmer_exports_t *exports = NULL; wasmer_instance_exports(instance, &exports); int exports_len = wasmer_exports_len(exports); - printf("exports_len: %d\n", exports_len); + printf("exports_len: %d\n", exports_len); assert(exports_len == 1); wasmer_export_t *export = wasmer_exports_get(exports, 0); From a59ce13810f16e7cf0b254fecb3615218c00d921 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 27 Mar 2019 10:50:40 +0100 Subject: [PATCH 4/4] chore(runtime-c-api) Build the C and C++ headers. --- lib/runtime-c-api/wasmer.h | 16 ++++++++++++---- lib/runtime-c-api/wasmer.hh | 14 ++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 7461b4d1fa8..d11deab1115 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -66,6 +66,10 @@ typedef struct { typedef struct { +} wasmer_memory_t; + +typedef struct { + } wasmer_exports_t; typedef struct { @@ -99,10 +103,6 @@ typedef struct { typedef struct { -} wasmer_memory_t; - -typedef struct { - } wasmer_table_t; typedef union { @@ -241,6 +241,14 @@ wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); */ const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); +/** + * Gets a memory pointer from an export pointer. + * Returns `wasmer_result_t::WASMER_OK` upon success. + * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` + * and `wasmer_last_error_message` to get an error message. + */ +wasmer_result_t wasmer_export_to_memory(const wasmer_export_t *export_, wasmer_memory_t **memory); + /** * Frees the memory for the given exports */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index d90c22910f5..7b22732d090 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -61,6 +61,10 @@ struct wasmer_export_t { }; +struct wasmer_memory_t { + +}; + struct wasmer_exports_t { }; @@ -94,10 +98,6 @@ struct wasmer_instance_context_t { }; -struct wasmer_memory_t { - -}; - struct wasmer_table_t { }; @@ -210,6 +210,12 @@ wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); /// Gets export func from export const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); +/// Gets a memory pointer from an export pointer. +/// Returns `wasmer_result_t::WASMER_OK` upon success. +/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` +/// and `wasmer_last_error_message` to get an error message. +wasmer_result_t wasmer_export_to_memory(const wasmer_export_t *export_, wasmer_memory_t **memory); + /// Frees the memory for the given exports void wasmer_exports_destroy(wasmer_exports_t *exports);