diff --git a/lib/runtime-c-api/src/export.rs b/lib/runtime-c-api/src/export.rs index 20bb91c7cc9..d6dfa5d973b 100644 --- a/lib/runtime-c-api/src/export.rs +++ b/lib/runtime-c-api/src/export.rs @@ -11,7 +11,7 @@ use crate::{ value::{wasmer_value, wasmer_value_t, wasmer_value_tag}, wasmer_byte_array, wasmer_result_t, }; -use libc::c_int; +use libc::{c_int, c_uint}; use std::{ptr, slice}; use wasmer_runtime::{Instance, Memory, Module, Value}; use wasmer_runtime_core::{export::Export, module::ExportIndex}; @@ -390,9 +390,9 @@ pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> was pub unsafe extern "C" fn wasmer_export_func_call( func: *const wasmer_export_func_t, params: *const wasmer_value_t, - params_len: c_int, + params_len: c_uint, results: *mut wasmer_value_t, - results_len: c_int, + results_len: c_uint, ) -> wasmer_result_t { if func.is_null() { update_last_error(CApiError { @@ -400,15 +400,25 @@ pub unsafe extern "C" fn wasmer_export_func_call( }); return wasmer_result_t::WASMER_ERROR; } - if params.is_null() { + + if params_len > 0 && params.is_null() { update_last_error(CApiError { msg: "params ptr is null".to_string(), }); return wasmer_result_t::WASMER_ERROR; } - let params: &[wasmer_value_t] = slice::from_raw_parts(params, params_len as usize); - let params: Vec = params.iter().cloned().map(|x| x.into()).collect(); + let params: Vec = { + if params_len <= 0 { + vec![] + } else { + slice::from_raw_parts::(params, params_len as usize) + .iter() + .cloned() + .map(|x| x.into()) + .collect() + } + }; let named_export = &*(func as *mut NamedExport); diff --git a/lib/runtime-c-api/tests/assets/exports.rs b/lib/runtime-c-api/tests/assets/exports.rs new file mode 100644 index 00000000000..9e55985cf1c --- /dev/null +++ b/lib/runtime-c-api/tests/assets/exports.rs @@ -0,0 +1,37 @@ +#[no_mangle] +pub extern "C" fn sum(x: i32, y: i32) -> i32 { + x + y +} + +#[no_mangle] +pub extern "C" fn arity_0() -> i32 { + 42 +} + +#[no_mangle] +pub extern "C" fn i32_i32(x: i32) -> i32 { + x +} + +#[no_mangle] +pub extern "C" fn i64_i64(x: i64) -> i64 { + x +} + +#[no_mangle] +pub extern "C" fn f32_f32(x: f32) -> f32 { + x +} + +#[no_mangle] +pub extern "C" fn f64_f64(x: f64) -> f64 { + x +} + +#[no_mangle] +pub extern "C" fn string() -> *const u8 { + b"Hello, World!\0".as_ptr() +} + +#[no_mangle] +pub extern "C" fn void() {} diff --git a/lib/runtime-c-api/tests/assets/exports.wasm b/lib/runtime-c-api/tests/assets/exports.wasm new file mode 100644 index 00000000000..6bea6de3369 Binary files /dev/null and b/lib/runtime-c-api/tests/assets/exports.wasm differ diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 77ff6683be1..5ca9aaa5601 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -5,81 +5,483 @@ int main() { - // Read the wasm file bytes - FILE *file = fopen("assets/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); + // Read the WebAssembly bytes. + uint8_t *wasm_bytes = NULL; + long wasm_bytes_length = 0; + + { + FILE *file = fopen("assets/exports.wasm", "r"); + fseek(file, 0, SEEK_END); + wasm_bytes_length = ftell(file); + wasm_bytes = (uint8_t *) malloc(wasm_bytes_length); + fseek(file, 0, SEEK_SET); + fread(wasm_bytes, 1, wasm_bytes_length, file); + fclose(file); + } 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); + wasmer_result_t compile_result = wasmer_instantiate(&instance, wasm_bytes, wasm_bytes_length, imports, 0); + 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); - assert(exports_len == 1); + int exports_length = wasmer_exports_len(exports); + printf("Number of exports: %d\n", exports_length); + + { + printf("\nCheck the `sum` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 3); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 3); + + char expected[] = {'s', 'u', 'm'}; + + printf("Read export name:\n"); + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + printf("%c\n", name_bytes.bytes[idx]); + + assert(name_bytes.bytes[idx] == expected[idx]); + } + + printf("Check arity\n"); + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 2); + assert(outputs_arity == 1); + + printf("Check signature\n"); + + wasmer_value_tag *input_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * inputs_arity); + wasmer_export_func_params(exported_function, input_types , inputs_arity); + + assert(input_types[0] == WASM_I32); + assert(input_types[1] == WASM_I32); + + free(input_types); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); - wasmer_export_t *export = wasmer_exports_get(exports, 0); + assert(output_types[0] == WASM_I32); - wasmer_import_export_kind kind = wasmer_export_kind(export); - assert(kind == WASM_FUNCTION); - const wasmer_export_func_t *func = wasmer_export_to_func(export); + free(output_types); - wasmer_byte_array name_bytes = wasmer_export_name(export); - assert(name_bytes.bytes_len == 3); - char expected[] = {'s', 'u', 'm'}; - for(int idx = 0; idx < 3; idx++){ - printf("%c\n", name_bytes.bytes[idx]); - assert(name_bytes.bytes[idx] == expected[idx]); + printf("Call the exported function\n"); + + wasmer_value_t input_0; + input_0.tag = WASM_I32; + input_0.value.I32 = 7; + + wasmer_value_t input_1; + input_1.tag = WASM_I32; + input_1.value.I32 = 8; + + wasmer_value_t inputs[] = {input_0, input_1}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Call result: %d\n", call_result); + printf("Result: %d\n", outputs[0].value.I32); + + assert(outputs[0].value.I32 == 15); + assert(call_result == WASMER_OK); } - uint32_t params_arity; - wasmer_export_func_params_arity(func, ¶ms_arity); - assert(params_arity == 2); - - wasmer_value_tag *params_sig = malloc(sizeof(wasmer_value_tag) * params_arity); - wasmer_export_func_params(func, params_sig , params_arity); - assert(params_sig[0] == WASM_I32); - assert(params_sig[1] == WASM_I32); - free(params_sig); - - uint32_t returns_arity; - wasmer_export_func_returns_arity(func, &returns_arity); - assert(returns_arity == 1); - - wasmer_value_tag *returns_sig = malloc(sizeof(wasmer_value_tag) * returns_arity); - wasmer_export_func_returns(func, returns_sig , returns_arity); - assert(returns_sig[0] == WASM_I32); - free(returns_sig); - - 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_export_func_call(func, params, params_arity, results, returns_arity); - 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); - - - printf("Destroy instance\n"); + { + printf("\nCheck the `arity_0` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 4); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 7); + + char expected[] = {'a', 'r', 'i', 't', 'y', '_', '0'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 0); + assert(outputs_arity == 1); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_I32); + + free(output_types); + + wasmer_value_t inputs[] = {}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %d\n", outputs[0].value.I32); + + assert(outputs[0].value.I32 == 42); + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `i32_i32` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 5); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 7); + + char expected[] = {'i', '3', '2', '_', 'i', '3', '2'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 1); + assert(outputs_arity == 1); + + wasmer_value_tag *input_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * inputs_arity); + wasmer_export_func_params(exported_function, input_types , inputs_arity); + + assert(input_types[0] == WASM_I32); + + free(input_types); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_I32); + + free(output_types); + + wasmer_value_t input_0; + input_0.tag = WASM_I32; + input_0.value.I32 = 7; + wasmer_value_t inputs[] = {input_0}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %d\n", outputs[0].value.I32); + + assert(outputs[0].value.I32 == 7); + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `i64_i64` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 6); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 7); + + char expected[] = {'i', '6', '4', '_', 'i', '6', '4'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 1); + assert(outputs_arity == 1); + + wasmer_value_tag *input_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * inputs_arity); + wasmer_export_func_params(exported_function, input_types , inputs_arity); + + assert(input_types[0] == WASM_I64); + + free(input_types); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_I64); + + free(output_types); + + wasmer_value_t input_0; + input_0.tag = WASM_I64; + input_0.value.I64 = 7; + wasmer_value_t inputs[] = {input_0}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %lld\n", outputs[0].value.I64); + + assert(outputs[0].value.I64 == 7); + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `f32_f32` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 7); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 7); + + char expected[] = {'f', '3', '2', '_', 'f', '3', '2'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 1); + assert(outputs_arity == 1); + + wasmer_value_tag *input_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * inputs_arity); + wasmer_export_func_params(exported_function, input_types , inputs_arity); + + assert(input_types[0] == WASM_F32); + + free(input_types); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_F32); + + free(output_types); + + wasmer_value_t input_0; + input_0.tag = WASM_F32; + input_0.value.F32 = 7.42; + wasmer_value_t inputs[] = {input_0}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %f\n", outputs[0].value.F32); + + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `f64_f64` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 8); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 7); + + char expected[] = {'f', '6', '4', '_', 'f', '6', '4'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 1); + assert(outputs_arity == 1); + + wasmer_value_tag *input_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * inputs_arity); + wasmer_export_func_params(exported_function, input_types , inputs_arity); + + assert(input_types[0] == WASM_F64); + + free(input_types); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_F64); + + free(output_types); + + wasmer_value_t input_0; + input_0.tag = WASM_F64; + input_0.value.F64 = 7.42; + wasmer_value_t inputs[] = {input_0}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %f\n", outputs[0].value.F64); + + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `string` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 9); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 6); + + char expected[] = {'s', 't', 'r', 'i', 'n', 'g'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 0); + assert(outputs_arity == 1); + + wasmer_value_tag *output_types = (wasmer_value_tag *) malloc(sizeof(wasmer_value_tag) * outputs_arity); + wasmer_export_func_returns(exported_function, output_types, outputs_arity); + + assert(output_types[0] == WASM_I32); + + free(output_types); + + wasmer_value_t inputs[] = {}; + + wasmer_value_t output_0; + wasmer_value_t outputs[] = {output_0}; + + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + + printf("Result: %d\n", outputs[0].value.I32); + + assert(outputs[0].value.I32 == 1048576); + assert(call_result == WASMER_OK); + } + + { + printf("\nCheck the `void` exported function\n"); + + wasmer_export_t *export = wasmer_exports_get(exports, 10); + wasmer_import_export_kind export_kind = wasmer_export_kind(export); + + assert(export_kind == WASM_FUNCTION); + + const wasmer_export_func_t *exported_function = wasmer_export_to_func(export); + wasmer_byte_array name_bytes = wasmer_export_name(export); + + assert(name_bytes.bytes_len == 4); + + char expected[] = {'v', 'o' , 'i', 'd'}; + + for (uint32_t idx = 0; idx < name_bytes.bytes_len; idx++) { + assert(name_bytes.bytes[idx] == expected[idx]); + } + + uint32_t inputs_arity; + wasmer_export_func_params_arity(exported_function, &inputs_arity); + + uint32_t outputs_arity; + wasmer_export_func_returns_arity(exported_function, &outputs_arity); + + assert(inputs_arity == 0); + assert(outputs_arity == 0); + + wasmer_value_t inputs[] = {}; + wasmer_value_t outputs[] = {}; + + { + wasmer_result_t call_result = wasmer_export_func_call(exported_function, inputs, inputs_arity, outputs, outputs_arity); + assert(call_result == WASMER_OK); + } + + { + wasmer_result_t call_result = wasmer_export_func_call(exported_function, NULL, inputs_arity, NULL, outputs_arity); + assert(call_result == WASMER_OK); + } + } + + printf("\nDestroy instance\n"); + wasmer_instance_destroy(instance); + printf("Destroy exports\n"); + wasmer_exports_destroy(exports); + return 0; } diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 816dbfeac9e..447d3107597 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -172,7 +172,9 @@ typedef struct { /** * Creates a new Module from the given wasm bytes. + * * 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. */ @@ -192,6 +194,7 @@ wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *expo /** * Gets export descriptors for the given module + * * The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. */ void wasmer_export_descriptors(const wasmer_module_t *module, @@ -216,19 +219,23 @@ int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); /** * Calls a `func` with the provided parameters. * Results are set using the provided `results` 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_func_call(const wasmer_export_func_t *func, const wasmer_value_t *params, - int params_len, + unsigned int params_len, wasmer_value_t *results, - int results_len); + unsigned int results_len); /** * Sets the params buffer to the parameter types of the given wasmer_export_func_t + * * 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. */ @@ -238,7 +245,9 @@ wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, /** * Sets the result parameter to the arity of the params of the wasmer_export_func_t + * * 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. */ @@ -246,7 +255,9 @@ wasmer_result_t wasmer_export_func_params_arity(const wasmer_export_func_t *func /** * Sets the returns buffer to the parameter types of the given wasmer_export_func_t + * * 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. */ @@ -256,7 +267,9 @@ wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, /** * Sets the result parameter to the arity of the returns of the wasmer_export_func_t + * * 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. */ @@ -280,7 +293,9 @@ 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. */ @@ -344,6 +359,7 @@ wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *impo /** * Gets import descriptors for the given module + * * The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. */ void wasmer_import_descriptors(const wasmer_module_t *module, @@ -372,6 +388,7 @@ void wasmer_import_func_destroy(wasmer_import_func_t *func); /** * Creates new func + * * The caller owns the object and should call `wasmer_import_func_destroy` to free it. */ wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), @@ -382,7 +399,9 @@ wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), /** * Sets the params buffer to the parameter types of the given wasmer_import_func_t + * * 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. */ @@ -392,7 +411,9 @@ wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, /** * Sets the result parameter to the arity of the params of the wasmer_import_func_t + * * 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. */ @@ -400,7 +421,9 @@ wasmer_result_t wasmer_import_func_params_arity(const wasmer_import_func_t *func /** * Sets the returns buffer to the parameter types of the given wasmer_import_func_t + * * 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. */ @@ -410,7 +433,9 @@ wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, /** * Sets the result parameter to the arity of the returns of the wasmer_import_func_t + * * 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. */ @@ -438,7 +463,9 @@ wasmer_import_object_t *wasmer_import_object_new(void); /** * Calls an instances exported function by `name` with the provided parameters. * Results are set using the provided `results` 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. */ @@ -479,13 +506,16 @@ void wasmer_instance_destroy(wasmer_instance_t *instance); /** * Gets Exports for the given instance + * * The caller owns the object and should call `wasmer_exports_destroy` to free it. */ void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); /** * Creates a new Instance from the given wasm bytes and imports. + * * 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. */ @@ -499,7 +529,9 @@ wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, * Gets the length in bytes of the last error. * This can be used to dynamically allocate a buffer with the correct number of * bytes needed to store a message. + * * # Example + * * ```c * int error_len = wasmer_last_error_length(); * char *error_str = malloc(error_len); @@ -510,9 +542,12 @@ int wasmer_last_error_length(void); /** * Stores the last error message into the provided buffer up to the given `length`. * The `length` parameter must be large enough to store the last error message. + * * Returns the length of the string in bytes. * Returns `-1` if an error occurs. + * * # Example + * * ```c * int error_len = wasmer_last_error_length(); * char *error_str = malloc(error_len); @@ -539,7 +574,9 @@ void wasmer_memory_destroy(wasmer_memory_t *memory); /** * Grows a Memory by the given number of pages. + * * 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. */ @@ -553,8 +590,11 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory); /** * Creates a new Memory for the given descriptor and initializes the given * pointer to pointer to a pointer to the new memory. + * * The caller owns the object and should call `wasmer_memory_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. */ @@ -562,7 +602,9 @@ wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limi /** * 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. */ @@ -576,8 +618,9 @@ void wasmer_module_destroy(wasmer_module_t *module); /** * Given: - * A prepared `wasmer` import-object - * A compiled wasmer module + * * A prepared `wasmer` import-object + * * A compiled wasmer module + * * Instantiates a wasmer instance */ wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance, @@ -586,7 +629,9 @@ wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance, /** * Creates a new Instance from the given module and imports. + * * 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. */ @@ -597,8 +642,11 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, /** * 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. */ @@ -617,8 +665,11 @@ void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_mod /** * 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. */ @@ -633,7 +684,9 @@ void wasmer_table_destroy(wasmer_table_t *table); /** * Grows a Table by the given number of elements. + * * 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. */ @@ -647,8 +700,11 @@ uint32_t wasmer_table_length(wasmer_table_t *table); /** * Creates a new Table for the given descriptor and initializes the given * pointer to pointer to a pointer to the new Table. + * * The caller owns the object and should call `wasmer_table_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. */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index afe82536466..d372d8eb3e2 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -157,7 +157,9 @@ struct wasmer_trampoline_buffer_t { extern "C" { /// Creates a new Module from the given wasm bytes. +/// /// 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_compile(wasmer_module_t **module, @@ -171,6 +173,7 @@ wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *export_descriptor); /// Gets export descriptors for the given module +/// /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. void wasmer_export_descriptors(const wasmer_module_t *module, wasmer_export_descriptors_t **export_descriptors); @@ -187,17 +190,21 @@ int wasmer_export_descriptors_len(wasmer_export_descriptors_t *exports); /// Calls a `func` with the provided parameters. /// Results are set using the provided `results` 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_func_call(const wasmer_export_func_t *func, const wasmer_value_t *params, - int params_len, + unsigned int params_len, wasmer_value_t *results, - int results_len); + unsigned int results_len); /// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// /// 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_func_params(const wasmer_export_func_t *func, @@ -205,13 +212,17 @@ wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, uint32_t params_len); /// Sets the result parameter to the arity of the params of the wasmer_export_func_t +/// /// 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_func_params_arity(const wasmer_export_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// /// 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_func_returns(const wasmer_export_func_t *func, @@ -219,7 +230,9 @@ wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, uint32_t returns_len); /// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// /// 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_func_returns_arity(const wasmer_export_func_t *func, @@ -235,7 +248,9 @@ 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); @@ -275,6 +290,7 @@ wasmer_byte_array wasmer_import_descriptor_module_name(wasmer_import_descriptor_ wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *import_descriptor); /// Gets import descriptors for the given module +/// /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. void wasmer_import_descriptors(const wasmer_module_t *module, wasmer_import_descriptors_t **import_descriptors); @@ -293,6 +309,7 @@ unsigned int wasmer_import_descriptors_len(wasmer_import_descriptors_t *exports) void wasmer_import_func_destroy(wasmer_import_func_t *func); /// Creates new func +/// /// The caller owns the object and should call `wasmer_import_func_destroy` to free it. wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), const wasmer_value_tag *params, @@ -301,7 +318,9 @@ wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), unsigned int returns_len); /// Sets the params buffer to the parameter types of the given wasmer_import_func_t +/// /// 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_import_func_params(const wasmer_import_func_t *func, @@ -309,13 +328,17 @@ wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, unsigned int params_len); /// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// /// 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_import_func_params_arity(const wasmer_import_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_import_func_t +/// /// 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_import_func_returns(const wasmer_import_func_t *func, @@ -323,7 +346,9 @@ wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, unsigned int returns_len); /// Sets the result parameter to the arity of the returns of the wasmer_import_func_t +/// /// 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_import_func_returns_arity(const wasmer_import_func_t *func, @@ -343,7 +368,9 @@ wasmer_import_object_t *wasmer_import_object_new(); /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` 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_instance_call(wasmer_instance_t *instance, @@ -372,11 +399,14 @@ const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_cont void wasmer_instance_destroy(wasmer_instance_t *instance); /// Gets Exports for the given instance +/// /// The caller owns the object and should call `wasmer_exports_destroy` to free it. void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); /// Creates a new Instance from the given wasm bytes and imports. +/// /// 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_instantiate(wasmer_instance_t **instance, @@ -388,7 +418,9 @@ wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, /// Gets the length in bytes of the last error. /// This can be used to dynamically allocate a buffer with the correct number of /// bytes needed to store a message. +/// /// # Example +/// /// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); @@ -397,9 +429,12 @@ int wasmer_last_error_length(); /// Stores the last error message into the provided buffer up to the given `length`. /// The `length` parameter must be large enough to store the last error message. +/// /// Returns the length of the string in bytes. /// Returns `-1` if an error occurs. +/// /// # Example +/// /// ```c /// int error_len = wasmer_last_error_length(); /// char *error_str = malloc(error_len); @@ -418,7 +453,9 @@ uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); void wasmer_memory_destroy(wasmer_memory_t *memory); /// Grows a Memory by the given number of pages. +/// /// 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_memory_grow(wasmer_memory_t *memory, uint32_t delta); @@ -428,14 +465,19 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory); /// Creates a new Memory for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new memory. +/// /// The caller owns the object and should call `wasmer_memory_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_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, @@ -445,15 +487,18 @@ wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module, void wasmer_module_destroy(wasmer_module_t *module); /// Given: -/// A prepared `wasmer` import-object -/// A compiled wasmer module +/// * A prepared `wasmer` import-object +/// * A compiled wasmer module +/// /// Instantiates a wasmer instance wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance, const wasmer_module_t *module, const wasmer_import_object_t *import_object); /// Creates a new Instance from the given module and imports. +/// /// 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_instantiate(const wasmer_module_t *module, @@ -462,8 +507,11 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, 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, @@ -476,8 +524,11 @@ wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_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, @@ -488,7 +539,9 @@ wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t * void wasmer_table_destroy(wasmer_table_t *table); /// Grows a Table by the given number of elements. +/// /// 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_table_grow(wasmer_table_t *table, uint32_t delta); @@ -498,8 +551,11 @@ uint32_t wasmer_table_length(wasmer_table_t *table); /// Creates a new Table for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new Table. +/// /// The caller owns the object and should call `wasmer_table_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_table_new(wasmer_table_t **table, wasmer_limits_t limits);