mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-12 22:05:33 +00:00
wasmer-c-api:
* adding `wasmer_import_object_new` and `wasmer_import_object_extend` * adding test file `test-module-import-instantiate.c`
This commit is contained in:
parent
ab76755ade
commit
f73180f45e
@ -10,7 +10,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use std::{ffi::c_void, ptr, slice, sync::Arc};
|
use std::{ffi::c_void, ptr, slice, sync::Arc};
|
||||||
use wasmer_runtime::Module;
|
use wasmer_runtime::{Global, Memory, Module, Table};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
export::{Context, Export, FuncPointer},
|
export::{Context, Export, FuncPointer},
|
||||||
import::ImportObject,
|
import::ImportObject,
|
||||||
@ -41,6 +41,83 @@ pub struct wasmer_import_descriptor_t;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasmer_import_descriptors_t;
|
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
|
/// Gets import descriptors for the given module
|
||||||
///
|
///
|
||||||
/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it.
|
/// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it.
|
||||||
|
3
lib/runtime-c-api/tests/.gitignore
vendored
3
lib/runtime-c-api/tests/.gitignore
vendored
@ -22,4 +22,5 @@ test-module-exports
|
|||||||
test-module-imports
|
test-module-imports
|
||||||
test-module-serialize
|
test-module-serialize
|
||||||
test-tables
|
test-tables
|
||||||
test-validate
|
test-validate
|
||||||
|
test-module-import-instantiate
|
||||||
|
@ -14,6 +14,7 @@ add_executable(test-module-imports test-module-imports.c)
|
|||||||
add_executable(test-module-serialize test-module-serialize.c)
|
add_executable(test-module-serialize test-module-serialize.c)
|
||||||
add_executable(test-tables test-tables.c)
|
add_executable(test-tables test-tables.c)
|
||||||
add_executable(test-validate test-validate.c)
|
add_executable(test-validate test-validate.c)
|
||||||
|
add_executable(test-module-import-instantiate test-module-import-instantiate.c)
|
||||||
|
|
||||||
find_library(
|
find_library(
|
||||||
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll
|
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll
|
||||||
@ -87,3 +88,8 @@ add_test(test-tables test-tables)
|
|||||||
target_link_libraries(test-validate general ${WASMER_LIB})
|
target_link_libraries(test-validate general ${WASMER_LIB})
|
||||||
target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS})
|
target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS})
|
||||||
add_test(test-validate test-validate)
|
add_test(test-validate test-validate)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
BIN
lib/runtime-c-api/tests/assets/inc.wasm
Normal file
BIN
lib/runtime-c-api/tests/assets/inc.wasm
Normal file
Binary file not shown.
12
lib/runtime-c-api/tests/assets/inc.wast
Normal file
12
lib/runtime-c-api/tests/assets/inc.wast
Normal file
@ -0,0 +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))
|
@ -0,0 +1,148 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "../wasmer.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t amount;
|
||||||
|
int32_t value;
|
||||||
|
} counter_data;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* bytes;
|
||||||
|
long bytes_len;
|
||||||
|
} wasm_file_t;
|
||||||
|
|
||||||
|
wasm_file_t read_wasm_file(const char* file_name) {
|
||||||
|
wasm_file_t wasm_file;
|
||||||
|
|
||||||
|
FILE *file = fopen(file_name, "r");
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
wasm_file.bytes_len = ftell(file);
|
||||||
|
|
||||||
|
wasm_file.bytes = malloc(wasm_file.bytes_len);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
fread(wasm_file.bytes, 1, wasm_file.bytes_len, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return wasm_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc_counter(wasmer_instance_context_t *ctx) {
|
||||||
|
counter_data* data = (counter_data*)wasmer_instance_context_data_get(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter_data *init_counter(int32_t value, int32_t amount) {
|
||||||
|
counter_data* counter = malloc(sizeof(counter_data));
|
||||||
|
counter->value = value;
|
||||||
|
counter->amount = amount;
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
wasmer_import_t create_import(char* module_name, char* import_name, wasmer_import_func_t *func) {
|
||||||
|
wasmer_import_t import;
|
||||||
|
wasmer_byte_array module_name_bytes;
|
||||||
|
wasmer_byte_array import_name_bytes;
|
||||||
|
|
||||||
|
module_name_bytes.bytes = (const uint8_t *) module_name;
|
||||||
|
module_name_bytes.bytes_len = strlen(module_name);
|
||||||
|
|
||||||
|
import_name_bytes.bytes = (const uint8_t *) import_name;
|
||||||
|
import_name_bytes.bytes_len = strlen(import_name);
|
||||||
|
|
||||||
|
import.module_name = module_name_bytes;
|
||||||
|
import.import_name = import_name_bytes;
|
||||||
|
|
||||||
|
import.tag = WASM_FUNCTION;
|
||||||
|
import.value.func = func;
|
||||||
|
|
||||||
|
return import;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Prepare Imports
|
||||||
|
wasmer_value_tag inc_params_sig[] = {};
|
||||||
|
wasmer_value_tag inc_returns_sig[] = {};
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Read the wasm file
|
||||||
|
wasm_file_t wasm_file = read_wasm_file("assets/inc.wasm");
|
||||||
|
|
||||||
|
// Compile module
|
||||||
|
wasmer_module_t *module = NULL;
|
||||||
|
wasmer_result_t compile_res = wasmer_compile(&module, wasm_file.bytes, wasm_file.bytes_len);
|
||||||
|
assert(compile_res == WASMER_OK);
|
||||||
|
|
||||||
|
// Prepare Import Object
|
||||||
|
wasmer_import_object_t *import_object = wasmer_import_object_new();
|
||||||
|
|
||||||
|
// First, we import `inc_counter` and `mul_counter`
|
||||||
|
wasmer_import_t imports[] = {inc_import, mul_import};
|
||||||
|
wasmer_result_t extend_res = wasmer_import_object_extend(import_object, imports, 2);
|
||||||
|
assert(extend_res == WASMER_OK);
|
||||||
|
|
||||||
|
// Now, we'll import `inc_counter` and `mul_counter`
|
||||||
|
wasmer_import_t more_imports[] = {get_import};
|
||||||
|
wasmer_result_t extend_res2 = wasmer_import_object_extend(import_object, more_imports, 1);
|
||||||
|
assert(extend_res2 == WASMER_OK);
|
||||||
|
|
||||||
|
// Same `wasmer_import_object_extend` as the first, doesn't affect anything
|
||||||
|
wasmer_result_t extend_res3 = wasmer_import_object_extend(import_object, imports, 2);
|
||||||
|
assert(extend_res3 == WASMER_OK);
|
||||||
|
|
||||||
|
// Instantiate instance
|
||||||
|
printf("Instantiating\n");
|
||||||
|
wasmer_instance_t *instance = NULL;
|
||||||
|
wasmer_result_t instantiate_res = wasmer_module_import_instantiate(&instance, module, import_object);
|
||||||
|
printf("Compile result: %d\n", instantiate_res);
|
||||||
|
|
||||||
|
// Init counter
|
||||||
|
counter_data *counter = init_counter(2, 5);
|
||||||
|
wasmer_instance_context_data_set(instance, counter);
|
||||||
|
|
||||||
|
wasmer_value_t result_one;
|
||||||
|
wasmer_value_t params[] = {};
|
||||||
|
wasmer_value_t results[] = {result_one};
|
||||||
|
|
||||||
|
wasmer_result_t call1_result = wasmer_instance_call(instance, "inc_and_get", params, 0, results, 1);
|
||||||
|
printf("Call result: %d\n", call1_result);
|
||||||
|
printf("Result: %d\n", results[0].value.I32);
|
||||||
|
|
||||||
|
wasmer_result_t call2_result = wasmer_instance_call(instance, "mul_and_get", params, 0, results, 1);
|
||||||
|
printf("Call result: %d\n", call2_result);
|
||||||
|
printf("Result: %d\n", results[0].value.I32);
|
||||||
|
|
||||||
|
// Clear resources
|
||||||
|
wasmer_import_func_destroy(inc_func);
|
||||||
|
wasmer_import_func_destroy(mul_func);
|
||||||
|
wasmer_import_func_destroy(get_func);
|
||||||
|
wasmer_instance_destroy(instance);
|
||||||
|
free(counter);
|
||||||
|
free(wasm_file.bytes);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -99,14 +99,6 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
} wasmer_instance_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
} wasmer_instance_context_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
} wasmer_table_t;
|
} wasmer_table_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@ -123,6 +115,14 @@ typedef struct {
|
|||||||
wasmer_import_export_value value;
|
wasmer_import_export_value value;
|
||||||
} wasmer_import_t;
|
} wasmer_import_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} wasmer_instance_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} wasmer_instance_context_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool has_some;
|
bool has_some;
|
||||||
uint32_t some;
|
uint32_t some;
|
||||||
@ -401,6 +401,19 @@ wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *fun
|
|||||||
*/
|
*/
|
||||||
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
|
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends an existing import object with new imports
|
||||||
|
*/
|
||||||
|
wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object,
|
||||||
|
wasmer_import_t *imports,
|
||||||
|
unsigned int imports_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new empty import object.
|
||||||
|
* See also `wasmer_import_object_append`
|
||||||
|
*/
|
||||||
|
wasmer_import_object_t *wasmer_import_object_new(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls an instances exported function by `name` with the provided parameters.
|
* Calls an instances exported function by `name` with the provided parameters.
|
||||||
* Results are set using the provided `results` pointer.
|
* Results are set using the provided `results` pointer.
|
||||||
|
@ -95,14 +95,6 @@ struct wasmer_import_object_t {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wasmer_instance_t {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wasmer_instance_context_t {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wasmer_table_t {
|
struct wasmer_table_t {
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -121,6 +113,14 @@ struct wasmer_import_t {
|
|||||||
wasmer_import_export_value value;
|
wasmer_import_export_value value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wasmer_instance_t {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wasmer_instance_context_t {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct wasmer_limit_option_t {
|
struct wasmer_limit_option_t {
|
||||||
bool has_some;
|
bool has_some;
|
||||||
uint32_t some;
|
uint32_t some;
|
||||||
@ -325,6 +325,15 @@ wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *fun
|
|||||||
/// Frees memory of the given ImportObject
|
/// Frees memory of the given ImportObject
|
||||||
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
|
void wasmer_import_object_destroy(wasmer_import_object_t *import_object);
|
||||||
|
|
||||||
|
/// Extends an existing import object with new imports
|
||||||
|
wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object,
|
||||||
|
wasmer_import_t *imports,
|
||||||
|
unsigned int imports_len);
|
||||||
|
|
||||||
|
/// Creates a new empty import object.
|
||||||
|
/// See also `wasmer_import_object_append`
|
||||||
|
wasmer_import_object_t *wasmer_import_object_new();
|
||||||
|
|
||||||
/// Calls an instances exported function by `name` with the provided parameters.
|
/// Calls an instances exported function by `name` with the provided parameters.
|
||||||
/// Results are set using the provided `results` pointer.
|
/// Results are set using the provided `results` pointer.
|
||||||
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
/// Returns `wasmer_result_t::WASMER_OK` upon success.
|
||||||
|
@ -51,7 +51,7 @@ pub struct ImportObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ImportObject {
|
impl ImportObject {
|
||||||
/// Create a new `ImportObject`.
|
/// Create a new `ImportObject`.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
map: Rc::new(RefCell::new(HashMap::new())),
|
map: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
Loading…
Reference in New Issue
Block a user