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

runtime-c-api: create the import object separately from instance instantiation #616

Merged
merged 9 commits into from
Aug 2, 2019
91 changes: 90 additions & 1 deletion lib/runtime-c-api/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use crate::{
};
use libc::c_uint;
use std::{ffi::c_void, ptr, slice, sync::Arc};
use wasmer_runtime::Module;
use wasmer_runtime::{Global, Memory, Module, Table};
use wasmer_runtime_core::{
export::{Context, Export, FuncPointer},
import::ImportObject,
module::ImportName,
types::{FuncSig, Type},
};
Expand All @@ -25,6 +26,9 @@ pub struct wasmer_import_t {
pub value: wasmer_import_export_value,
}

#[repr(C)]
pub struct wasmer_import_object_t;

#[repr(C)]
#[derive(Clone)]
pub struct wasmer_import_func_t;
Expand All @@ -37,6 +41,83 @@ pub struct wasmer_import_descriptor_t;
#[derive(Clone)]
pub struct wasmer_import_descriptors_t;

/// Creates a new empty import object.
/// See also `wasmer_import_object_append`
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_new() -> *mut wasmer_import_object_t {
let import_object = Box::new(ImportObject::new());

Box::into_raw(import_object) as *mut wasmer_import_object_t
}

/// Extends an existing import object with new imports
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub unsafe extern "C" fn wasmer_import_object_extend(
import_object: *mut wasmer_import_object_t,
imports: *mut wasmer_import_t,
imports_len: c_uint,
) -> wasmer_result_t {
let import_object: &mut ImportObject = &mut *(import_object as *mut ImportObject);

let mut extensions: Vec<(String, String, Export)> = Vec::new();

let imports: &[wasmer_import_t] = slice::from_raw_parts(imports, imports_len as usize);
for import in imports {
let module_name = slice::from_raw_parts(
import.module_name.bytes,
import.module_name.bytes_len as usize,
);
let module_name = if let Ok(s) = std::str::from_utf8(module_name) {
s
} else {
update_last_error(CApiError {
msg: "error converting module name to string".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
};
let import_name = slice::from_raw_parts(
import.import_name.bytes,
import.import_name.bytes_len as usize,
);
let import_name = if let Ok(s) = std::str::from_utf8(import_name) {
s
} else {
update_last_error(CApiError {
msg: "error converting import_name to string".to_string(),
});
return wasmer_result_t::WASMER_ERROR;
};

let export = match import.tag {
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())
}
};

let extension = (module_name.to_string(), import_name.to_string(), export);
extensions.push(extension)
}

import_object.extend(extensions);

return wasmer_result_t::WASMER_OK;
}

/// Gets import descriptors for the given module
///
/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it.
Expand Down Expand Up @@ -352,6 +433,14 @@ pub extern "C" fn wasmer_import_func_destroy(func: *mut wasmer_import_func_t) {
}
}

/// Frees memory of the given ImportObject
#[no_mangle]
pub extern "C" fn wasmer_import_object_destroy(import_object: *mut wasmer_import_object_t) {
if !import_object.is_null() {
unsafe { Box::from_raw(import_object as *mut ImportObject) };
}
}

struct NamedImportDescriptor {
module: String,
name: String,
Expand Down
36 changes: 33 additions & 3 deletions lib/runtime-c-api/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
use crate::{
error::{update_last_error, CApiError},
export::{wasmer_exports_t, wasmer_import_export_kind, NamedExport, NamedExports},
import::wasmer_import_t,
import::{wasmer_import_object_t, wasmer_import_t},
memory::wasmer_memory_t,
module::wasmer_module_t,
value::{wasmer_value, wasmer_value_t, wasmer_value_tag},
wasmer_result_t,
};
use libc::{c_char, c_int, c_void};
use std::{collections::HashMap, ffi::CStr, slice};
use wasmer_runtime::{Ctx, Global, ImportObject, Instance, Memory, Table, Value};
use wasmer_runtime_core::{export::Export, import::Namespace};
use wasmer_runtime::{Ctx, Global, Instance, Memory, Module, Table, Value};
use wasmer_runtime_core::{
export::Export,
import::{ImportObject, Namespace},
};

#[repr(C)]
pub struct wasmer_instance_t;
Expand Down Expand Up @@ -108,6 +112,32 @@ pub unsafe extern "C" fn wasmer_instantiate(
wasmer_result_t::WASMER_OK
}

/// Given:
/// * A prepared `wasmer` import-object
/// * A compiled wasmer module
///
/// Instantiates a wasmer instance
#[no_mangle]
pub unsafe extern "C" fn wasmer_module_import_instantiate(
instance: *mut *mut wasmer_instance_t,
module: *const wasmer_module_t,
import_object: *const wasmer_import_object_t,
) -> wasmer_result_t {
let import_object: &ImportObject = &*(import_object as *const ImportObject);
let module: &Module = &*(module as *const Module);

let new_instance: Instance = match module.instantiate(import_object) {
Ok(instance) => instance,
Err(error) => {
update_last_error(error);
return wasmer_result_t::WASMER_ERROR;
}
};
*instance = Box::into_raw(Box::new(new_instance)) as *mut wasmer_instance_t;

return wasmer_result_t::WASMER_OK;
}

/// Extracts the instance's context and returns it.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
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 @@ -24,3 +24,4 @@ test-module-serialize
test-tables
test-validate
test-context
test-module-import-instantiate
5 changes: 5 additions & 0 deletions lib/runtime-c-api/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_executable(test-module-serialize test-module-serialize.c)
add_executable(test-tables test-tables.c)
add_executable(test-validate test-validate.c)
add_executable(test-context test-context.c)
add_executable(test-module-import-instantiate test-module-import-instantiate.c)

find_library(
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll
Expand Down Expand Up @@ -92,3 +93,7 @@ add_test(test-validate test-validate)
target_link_libraries(test-context general ${WASMER_LIB})
target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS})
add_test(test-context test-context)

target_link_libraries(test-module-import-instantiate general ${WASMER_LIB})
target_compile_options(test-module-import-instantiate PRIVATE ${COMPILER_OPTIONS})
add_test(test-module-import-instantiate test-module-import-instantiate)
Binary file modified lib/runtime-c-api/tests/assets/inc.wasm
Binary file not shown.
5 changes: 5 additions & 0 deletions lib/runtime-c-api/tests/assets/inc.wast
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
(module
(func $inc (import "env" "inc"))
(func $mul (import "env" "mul"))
(func $get (import "env" "get") (result i32))

(func (export "inc_and_get") (result i32)
call $inc
call $get)

(func (export "mul_and_get") (result i32)
call $mul
call $get))
17 changes: 14 additions & 3 deletions lib/runtime-c-api/tests/test-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ void inc_counter(wasmer_instance_context_t *ctx) {
data->value = data->value + data->amount;
}

void mul_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
data->value = data->value * data->amount;
}

int32_t get_counter(wasmer_instance_context_t *ctx) {
counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx);
return data->value;
Expand Down Expand Up @@ -90,21 +95,27 @@ int main()
wasmer_import_func_t *inc_func = wasmer_import_func_new((void (*)(void *)) inc_counter, inc_params_sig, 0, inc_returns_sig, 0);
wasmer_import_t inc_import = create_import("env", "inc", inc_func);

wasmer_value_tag mul_params_sig[] = {};
wasmer_value_tag mul_returns_sig[] = {};
wasmer_import_func_t *mul_func = wasmer_import_func_new((void (*)(void *)) mul_counter, mul_params_sig, 0, mul_returns_sig, 0);
wasmer_import_t mul_import = create_import("env", "mul", mul_func);

wasmer_value_tag get_params_sig[] = {};
wasmer_value_tag get_returns_sig[] = {WASM_I32};
wasmer_import_func_t *get_func = wasmer_import_func_new((void (*)(void *)) get_counter, get_params_sig, 0, get_returns_sig, 1);
wasmer_import_t get_import = create_import("env", "get", get_func);

wasmer_import_t imports[] = {inc_import, get_import};
wasmer_import_t imports[] = {inc_import, mul_import, get_import};

// Read the wasm file
wasm_file_t wasm_file = read_wasm_file("assets/inc.wasm");

// Instantiate instance
printf("Instantiating\n");
wasmer_instance_t *instance = NULL;
wasmer_result_t compile_result = wasmer_instantiate(&instance, wasm_file.bytes, wasm_file.bytes_len, imports, 2);
printf("Compile result: %d\n", compile_result);
wasmer_result_t instantiate_res = wasmer_instantiate(&instance, wasm_file.bytes, wasm_file.bytes_len, imports, 3);
printf("Compile result: %d\n", instantiate_res);
assert(instantiate_res == WASMER_OK);

// Init counter
counter_data *counter = init_counter(2, 5);
Expand Down
Loading