mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 16:20:49 +00:00
Merge #271
271: feat: Implement `wasmer_module_serialize` and `wasmer_module_deserialize` functions in `runtime-c-api` r=Hywan a=Hywan This PR implements 5 new functions in the `runtime-c-api` crate: 1. `wasmer_module_serialize` to serialize a module into a `wasmer_serialized_module_t` type, 2. `wasmer_module_deserialize` to deserialize a serialized module, 3. `wasmer_serialized_module_bytes` to read the bytes in the `wasmer_serialized_module_t` type into a `wasmer_byte_array`, 4. `wasmer_serialized_module_from_bytes` to transform a `wasmer_byte_array` into a `wasmer_serialized_module_t`, 4. `wasmer_serialized_module_destroy` to destroy a `wasmer_serialized_module_t`. Documentation and a test suite have been added. We need to change the visibility of the `wasmer_runtime::default_compiler` function to public, since it is used in `runtime-c-api`. The new test suite `test-module-serialize` does a full roundtrip: A module is compiled, then serialized, then deserialized, to finally be instantiated and a function is called on it. Thoughts? Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
This commit is contained in:
commit
c101498aa9
@ -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<NamedExportDescriptor>);
|
||||
/// 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<NamedImportDescriptor>);
|
||||
/// 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<NamedExport>);
|
||||
/// 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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
13
lib/runtime-c-api/tests/.gitignore
vendored
13
lib/runtime-c-api/tests/.gitignore
vendored
@ -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
|
||||
test-validate
|
@ -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)
|
||||
|
93
lib/runtime-c-api/tests/test-module-serialize.c
Normal file
93
lib/runtime-c-api/tests/test-module-serialize.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include "../wasmer.h"
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
||||
|
@ -152,7 +152,8 @@ pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result<I
|
||||
module.instantiate(import_object)
|
||||
}
|
||||
|
||||
fn default_compiler() -> &'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")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user