diff --git a/lib/runtime-c-api/Cargo.toml b/lib/runtime-c-api/Cargo.toml index 201c400a066..c0f5cdef27c 100644 --- a/lib/runtime-c-api/Cargo.toml +++ b/lib/runtime-c-api/Cargo.toml @@ -8,13 +8,23 @@ repository = "https://github.com/wasmerio/wasmer" edition = "2018" readme = "README.md" +[lib] +crate-type = ["cdylib", "rlib", "staticlib"] + [dependencies] -wasmer-runtime = { path = "../runtime", version = "0.2.1" } -wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" } libc = "0.2" -[lib] -crate-type = ["cdylib", "rlib", "staticlib"] +[dependencies.wasmer-runtime] +path = "../runtime" +version = "0.2.1" + +[dependencies.wasmer-runtime-core] +path = "../runtime-core" +version = "0.2.1" + +[features] +debug = ["wasmer-runtime/debug"] +llvm = ["wasmer-runtime/llvm"] [build-dependencies] cbindgen = "0.8" \ No newline at end of file diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index a66f584e422..e83d54bf37c 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -10,9 +10,13 @@ use std::fmt; use std::slice; use std::sync::Arc; use std::{ffi::c_void, ptr}; -use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value}; +use wasmer_runtime::{ + default_compiler, Ctx, Global, ImportObject, Instance, Memory, Module, Table, Value, +}; +use wasmer_runtime_core::cache::Artifact; use wasmer_runtime_core::export::{Context, Export, FuncPointer}; use wasmer_runtime_core::import::Namespace; +use wasmer_runtime_core::load_cache_with; use wasmer_runtime_core::module::{ExportIndex, ImportName}; use wasmer_runtime_core::types::{ElementType, FuncSig, MemoryDescriptor, TableDescriptor, Type}; use wasmer_runtime_core::units::{Bytes, Pages}; @@ -20,6 +24,9 @@ use wasmer_runtime_core::units::{Bytes, Pages}; #[repr(C)] pub struct wasmer_module_t; +#[repr(C)] +pub struct wasmer_serialized_module_t; + #[repr(C)] pub struct wasmer_instance_t; @@ -165,7 +172,7 @@ pub unsafe extern "C" fn wasmer_validate( if wasm_bytes.is_null() { return false; } - let bytes: &[u8] = ::std::slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); + let bytes: &[u8] = slice::from_raw_parts(wasm_bytes, wasm_bytes_len as usize); wasmer_runtime_core::validate(bytes) } @@ -310,7 +317,7 @@ pub extern "C" fn wasmer_table_length(table: *mut wasmer_table_t) -> uint32_t { #[no_mangle] pub extern "C" fn wasmer_table_destroy(table: *mut wasmer_table_t) { if !table.is_null() { - drop(unsafe { Box::from_raw(table as *mut Table) }); + unsafe { Box::from_raw(table as *mut Table) }; } } @@ -365,7 +372,7 @@ pub extern "C" fn wasmer_global_get_descriptor( #[no_mangle] pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { if !global.is_null() { - drop(unsafe { Box::from_raw(global as *mut Global) }); + unsafe { Box::from_raw(global as *mut Global) }; } } @@ -374,7 +381,7 @@ pub extern "C" fn wasmer_global_destroy(global: *mut wasmer_global_t) { #[no_mangle] pub extern "C" fn wasmer_memory_destroy(memory: *mut wasmer_memory_t) { if !memory.is_null() { - drop(unsafe { Box::from_raw(memory as *mut Memory) }); + unsafe { Box::from_raw(memory as *mut Memory) }; } } @@ -391,7 +398,7 @@ pub unsafe extern "C" fn wasmer_compile( wasm_bytes: *mut uint8_t, wasm_bytes_len: uint32_t, ) -> wasmer_result_t { - let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); + let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let result = wasmer_runtime::compile(bytes); let new_module = match result { Ok(instance) => instance, @@ -509,13 +516,11 @@ pub struct NamedExportDescriptors(Vec); /// Frees the memory for the given export descriptors #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub unsafe extern "C" fn wasmer_export_descriptors_destroy( +pub extern "C" fn wasmer_export_descriptors_destroy( export_descriptors: *mut wasmer_export_descriptors_t, ) { if !export_descriptors.is_null() { - drop(Box::from_raw( - export_descriptors as *mut NamedExportDescriptors, - )); + unsafe { Box::from_raw(export_descriptors as *mut NamedExportDescriptors) }; } } @@ -569,12 +574,150 @@ pub unsafe extern "C" fn wasmer_export_descriptor_kind( named_export_descriptor.kind.clone() } +/// Serialize the given Module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// 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. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_serialize( + serialized_module: *mut *mut wasmer_serialized_module_t, + module: *const wasmer_module_t, +) -> wasmer_result_t { + let module = &*(module as *const Module); + + match module.cache() { + Ok(artifact) => match artifact.serialize() { + Ok(serialized_artifact) => { + *serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _; + + wasmer_result_t::WASMER_OK + } + Err(_) => { + update_last_error(CApiError { + msg: "Failed to serialize the module artifact".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + }, + Err(_) => { + update_last_error(CApiError { + msg: "Failed to serialize the module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Get bytes of the serialized module. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_serialized_module_bytes( + serialized_module: *const wasmer_serialized_module_t, +) -> wasmer_byte_array { + let serialized_module = &*(serialized_module as *const &[u8]); + + wasmer_byte_array { + bytes: serialized_module.as_ptr(), + bytes_len: serialized_module.len() as u32, + } +} + +/// Transform a sequence of bytes into a serialized module. +/// +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// +/// 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. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_serialized_module_from_bytes( + serialized_module: *mut *mut wasmer_serialized_module_t, + serialized_module_bytes: *const uint8_t, + serialized_module_bytes_length: uint32_t, +) -> wasmer_result_t { + if serialized_module.is_null() { + update_last_error(CApiError { + msg: "`serialized_module_bytes` pointer is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let serialized_module_bytes: &[u8] = slice::from_raw_parts( + serialized_module_bytes, + serialized_module_bytes_length as usize, + ); + + *serialized_module = Box::into_raw(Box::new(serialized_module_bytes)) as _; + wasmer_result_t::WASMER_OK +} + +/// Deserialize the given serialized module. +/// +/// 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. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_module_deserialize( + module: *mut *mut wasmer_module_t, + serialized_module: *const wasmer_serialized_module_t, +) -> wasmer_result_t { + if serialized_module.is_null() { + update_last_error(CApiError { + msg: "`serialized_module` pointer is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + + let serialized_module: &[u8] = &*(serialized_module as *const &[u8]); + + match Artifact::deserialize(serialized_module) { + Ok(artifact) => match load_cache_with(artifact, default_compiler()) { + Ok(deserialized_module) => { + *module = Box::into_raw(Box::new(deserialized_module)) as _; + wasmer_result_t::WASMER_OK + } + Err(_) => { + update_last_error(CApiError { + msg: "Failed to compile the serialized module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + }, + Err(_) => { + update_last_error(CApiError { + msg: "Failed to deserialize the module".to_string(), + }); + wasmer_result_t::WASMER_ERROR + } + } +} + +/// Frees memory for the given serialized Module. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub extern "C" fn wasmer_serialized_module_destroy( + serialized_module: *mut wasmer_serialized_module_t, +) { + if !serialized_module.is_null() { + unsafe { Box::from_raw(serialized_module as *mut &[u8]) }; + } +} + /// Frees memory for the given Module #[allow(clippy::cast_ptr_alignment)] #[no_mangle] pub extern "C" fn wasmer_module_destroy(module: *mut wasmer_module_t) { if !module.is_null() { - drop(unsafe { Box::from_raw(module as *mut Module) }); + unsafe { Box::from_raw(module as *mut Module) }; } } @@ -682,13 +825,11 @@ pub struct NamedImportDescriptors(Vec); /// Frees the memory for the given import descriptors #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub unsafe extern "C" fn wasmer_import_descriptors_destroy( +pub extern "C" fn wasmer_import_descriptors_destroy( import_descriptors: *mut wasmer_import_descriptors_t, ) { if !import_descriptors.is_null() { - drop(Box::from_raw( - import_descriptors as *mut NamedImportDescriptors, - )); + unsafe { Box::from_raw(import_descriptors as *mut NamedImportDescriptors) }; } } @@ -831,7 +972,7 @@ pub unsafe extern "C" fn wasmer_instantiate( import_object.register(module_name, namespace); } - let bytes: &[u8] = ::std::slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); + let bytes: &[u8] = slice::from_raw_parts_mut(wasm_bytes, wasm_bytes_len as usize); let result = wasmer_runtime::instantiate(bytes, &import_object); let new_instance = match result { Ok(instance) => instance, @@ -964,9 +1105,9 @@ pub struct NamedExports(Vec); /// Frees the memory for the given exports #[allow(clippy::cast_ptr_alignment)] #[no_mangle] -pub unsafe extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { +pub extern "C" fn wasmer_exports_destroy(exports: *mut wasmer_exports_t) { if !exports.is_null() { - drop(Box::from_raw(exports as *mut NamedExports)); + unsafe { Box::from_raw(exports as *mut NamedExports) }; } } @@ -1255,7 +1396,7 @@ pub unsafe extern "C" fn wasmer_import_func_returns_arity( #[no_mangle] pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) { if !func.is_null() { - drop(unsafe { Box::from_raw(func as *mut Export) }); + unsafe { Box::from_raw(func as *mut Export) }; } } @@ -1395,7 +1536,7 @@ pub extern "C" fn wasmer_memory_data_length(mem: *mut wasmer_memory_t) -> uint32 #[no_mangle] pub extern "C" fn wasmer_instance_destroy(instance: *mut wasmer_instance_t) { if !instance.is_null() { - drop(unsafe { Box::from_raw(instance as *mut Instance) }); + unsafe { Box::from_raw(instance as *mut Instance) }; } } diff --git a/lib/runtime-c-api/tests/.gitignore b/lib/runtime-c-api/tests/.gitignore index 15e33d2cf6e..b8f6888c2a7 100644 --- a/lib/runtime-c-api/tests/.gitignore +++ b/lib/runtime-c-api/tests/.gitignore @@ -9,15 +9,16 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps -test-globals +rust-build test-exports -test-instantiate -test-imports +test-globals test-import-function +test-imports +test-instantiate test-memory -test-module-imports test-module test-module-exports +test-module-imports +test-module-serialize test-tables -test-validate -rust-build \ No newline at end of file +test-validate \ No newline at end of file diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index c94c748e15d..136c0c1e919 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -1,17 +1,18 @@ cmake_minimum_required (VERSION 2.6) project (WasmerRuntimeCApiTests) -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) add_executable(test-import-function test-import-function.c) +add_executable(test-imports test-imports.c) +add_executable(test-instantiate test-instantiate.c) add_executable(test-memory test-memory.c) -add_executable(test-module-imports test-module-imports.c) add_executable(test-module test-module.c) add_executable(test-module-exports test-module-exports.c) -add_executable(test-validate test-validate.c) +add_executable(test-module-imports test-module-imports.c) +add_executable(test-module-serialize test-module-serialize.c) add_executable(test-tables test-tables.c) +add_executable(test-validate test-validate.c) find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll @@ -34,10 +35,6 @@ set( "/WX" > ) -target_link_libraries(test-imports general ${WASMER_LIB}) -target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) -add_test(test-imports test-imports) - target_link_libraries(test-exports general ${WASMER_LIB}) target_compile_options(test-exports PRIVATE ${COMPILER_OPTIONS}) add_test(test-exports test-exports) @@ -46,22 +43,22 @@ target_link_libraries(test-globals general ${WASMER_LIB}) target_compile_options(test-globals PRIVATE ${COMPILER_OPTIONS}) add_test(test-globals test-globals) -target_link_libraries(test-instantiate general ${WASMER_LIB}) -target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) -add_test(test-instantiate test-instantiate) - target_link_libraries(test-import-function general ${WASMER_LIB}) target_compile_options(test-import-function PRIVATE ${COMPILER_OPTIONS}) add_test(test-import-function test-import-function) +target_link_libraries(test-imports general ${WASMER_LIB}) +target_compile_options(test-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-imports test-imports) + +target_link_libraries(test-instantiate general ${WASMER_LIB}) +target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) +add_test(test-instantiate test-instantiate) + target_link_libraries(test-memory general ${WASMER_LIB}) target_compile_options(test-memory PRIVATE ${COMPILER_OPTIONS}) add_test(test-memory test-memory) -target_link_libraries(test-module-imports general ${WASMER_LIB}) -target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) -add_test(test-module-imports test-module-imports) - target_link_libraries(test-module general ${WASMER_LIB}) target_compile_options(test-module PRIVATE ${COMPILER_OPTIONS}) add_test(test-module test-module) @@ -70,10 +67,18 @@ target_link_libraries(test-module-exports general ${WASMER_LIB}) target_compile_options(test-module-exports PRIVATE ${COMPILER_OPTIONS}) add_test(test-module-exports test-module-exports) -target_link_libraries(test-validate general ${WASMER_LIB}) -target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) -add_test(test-validate test-validate) +target_link_libraries(test-module-imports general ${WASMER_LIB}) +target_compile_options(test-module-imports PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-imports test-module-imports) + +target_link_libraries(test-module-serialize general ${WASMER_LIB}) +target_compile_options(test-module-serialize PRIVATE ${COMPILER_OPTIONS}) +add_test(test-module-serialize test-module-serialize) target_link_libraries(test-tables general ${WASMER_LIB}) target_compile_options(test-tables PRIVATE ${COMPILER_OPTIONS}) add_test(test-tables test-tables) + +target_link_libraries(test-validate general ${WASMER_LIB}) +target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) +add_test(test-validate test-validate) diff --git a/lib/runtime-c-api/tests/test-module-serialize.c b/lib/runtime-c-api/tests/test-module-serialize.c new file mode 100644 index 00000000000..6f6a918813f --- /dev/null +++ b/lib/runtime-c-api/tests/test-module-serialize.c @@ -0,0 +1,93 @@ +#include +#include "../wasmer.h" +#include +#include + +int main() +{ + // Read the wasm file bytes + FILE *file = fopen("sum.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); + + wasmer_module_t *module_one = NULL; + wasmer_result_t compile_result = wasmer_compile(&module_one, bytes, len); + printf("Compile result: %d\n", compile_result); + assert(compile_result == WASMER_OK); + + wasmer_serialized_module_t *serialized_module = NULL; + wasmer_result_t serialize_result = wasmer_module_serialize(&serialized_module, module_one); + printf("Serialize result: %d\n", serialize_result); + assert(serialize_result == WASMER_OK); + + wasmer_byte_array serialized_module_bytes = wasmer_serialized_module_bytes(serialized_module); + printf("Serialized module pointer: %p\n", serialized_module_bytes.bytes); + printf("Serialized module length: %d\n", serialized_module_bytes.bytes_len); + assert(serialized_module_bytes.bytes != NULL); + assert(serialized_module_bytes.bytes_len > 8); + assert(serialized_module_bytes.bytes[0] == 'W'); + assert(serialized_module_bytes.bytes[1] == 'A'); + assert(serialized_module_bytes.bytes[2] == 'S'); + assert(serialized_module_bytes.bytes[3] == 'M'); + assert(serialized_module_bytes.bytes[4] == 'E'); + assert(serialized_module_bytes.bytes[5] == 'R'); + + wasmer_module_t *module_two = NULL; + wasmer_result_t unserialize_result = wasmer_module_deserialize(&module_two, serialized_module); + assert(unserialize_result == WASMER_OK); + + wasmer_import_t imports[] = {}; + wasmer_instance_t *instance = NULL; + wasmer_result_t instantiate_result = wasmer_module_instantiate(module_two, &instance, imports, 0); + printf("Instantiate result: %d\n", compile_result); + assert(instantiate_result == WASMER_OK); + + wasmer_value_t param_one; + param_one.tag = WASM_I32; + param_one.value.I32 = 7; + wasmer_value_t param_two; + param_two.tag = WASM_I32; + param_two.value.I32 = 8; + wasmer_value_t params[] = {param_one, param_two}; + + wasmer_value_t result_one; + wasmer_value_t results[] = {result_one}; + + wasmer_result_t call_result = wasmer_instance_call(instance, "sum", params, 2, results, 1); + printf("Call result: %d\n", call_result); + printf("Result: %d\n", results[0].value.I32); + assert(results[0].value.I32 == 15); + assert(call_result == WASMER_OK); + + wasmer_serialized_module_t *serialized_module_two = NULL; + wasmer_result_t serialized_module_from_bytes_result = wasmer_serialized_module_from_bytes( + &serialized_module_two, + serialized_module_bytes.bytes, + serialized_module_bytes.bytes_len + ); + assert(serialized_module_from_bytes_result == WASMER_OK); + + wasmer_module_t *module_three = NULL; + wasmer_result_t unserialized_result_two = wasmer_module_deserialize(&module_three, serialized_module_two); + assert(unserialized_result_two == WASMER_OK); + + wasmer_instance_t *instance_two = NULL; + wasmer_result_t instantiate_result_two = wasmer_module_instantiate(module_three, &instance, imports, 0); + assert(instantiate_result_two == WASMER_OK); + + printf("Destroy the serialized module\n"); + wasmer_serialized_module_destroy(serialized_module); + wasmer_serialized_module_destroy(serialized_module_two); + + printf("Destroy instance\n"); + wasmer_instance_destroy(instance); + + printf("Destroy modules\n"); + wasmer_module_destroy(module_one); + wasmer_module_destroy(module_two); + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 9a49d761787..7461b4d1fa8 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -129,6 +129,10 @@ typedef struct { wasmer_limit_option_t max; } wasmer_limits_t; +typedef struct { + +} wasmer_serialized_module_t; + /** * Creates a new Module from the given wasm bytes. * Returns `wasmer_result_t::WASMER_OK` upon success. @@ -488,6 +492,15 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory); */ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/** + * Deserialize the given serialized module. + * 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_module_deserialize(wasmer_module_t **module, + const wasmer_serialized_module_t *serialized_module); + /** * Frees memory for the given Module */ @@ -504,6 +517,37 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, wasmer_import_t *imports, int imports_len); +/** + * Serialize the given Module. + * The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. + * 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_module_serialize(wasmer_serialized_module_t **serialized_module, + const wasmer_module_t *module); + +/** + * Get bytes of the serialized module. + */ +wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module); + +/** + * Frees memory for the given serialized Module. + */ +void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module); + +/** + * Transform a sequence of bytes into a serialized module. + * The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. + * 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_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module, + const uint8_t *serialized_module_bytes, + uint32_t serialized_module_bytes_length); + /** * Frees memory for the given Table */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 97260fe4bfa..d90c22910f5 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -126,6 +126,10 @@ struct wasmer_limits_t { wasmer_limit_option_t max; }; +struct wasmer_serialized_module_t { + +}; + extern "C" { /// Creates a new Module from the given wasm bytes. @@ -385,6 +389,13 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory); /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); +/// Deserialize the given serialized module. +/// 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_module_deserialize(wasmer_module_t **module, + const wasmer_serialized_module_t *serialized_module); + /// Frees memory for the given Module void wasmer_module_destroy(wasmer_module_t *module); @@ -397,6 +408,29 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, wasmer_import_t *imports, int imports_len); +/// Serialize the given Module. +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// 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_module_serialize(wasmer_serialized_module_t **serialized_module, + const wasmer_module_t *module); + +/// Get bytes of the serialized module. +wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module); + +/// Frees memory for the given serialized Module. +void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module); + +/// Transform a sequence of bytes into a serialized module. +/// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// 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_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module, + const uint8_t *serialized_module_bytes, + uint32_t serialized_module_bytes_length); + /// Frees memory for the given Table void wasmer_table_destroy(wasmer_table_t *table); diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 55efcddec72..27945aa103b 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -152,7 +152,8 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result &'static dyn Compiler { +/// Get a single instance of the default compiler to use. +pub fn default_compiler() -> &'static dyn Compiler { use lazy_static::lazy_static; #[cfg(feature = "llvm")]