756: feat(runtime-c-api) Allow to call `wasmer_export_func_call` with null inputs and a 0 arity r=syrusakbary a=Hywan

Fix #753 

This PR allows to call `wasmer_export_func_call` with inputs set to NULL, and an arity of 0. It avoids to create an empty inputs array. So basically:

```c
wasmer_export_func_call(exported_function, NULL, 0, …, …);
```

instead of:

```c
wasmer_value_t inputs = {};
wasmer_export_func_call(exported_function, inputs, 0, …, …);
```

This PR also updates the test suite for exports. Instead of just the famous `sum` function, we now test more functions, so that all Wasm types are covered, including void functions.

Finally, this PR updates the `wasmer_export_func_call` signature to forbid negative arities.

Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
This commit is contained in:
bors[bot] 2019-09-06 11:56:45 +00:00 committed by GitHub
commit 20a0afa6a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 585 additions and 67 deletions

View File

@ -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<Value> = params.iter().cloned().map(|x| x.into()).collect();
let params: Vec<Value> = {
if params_len <= 0 {
vec![]
} else {
slice::from_raw_parts::<wasmer_value_t>(params, params_len as usize)
.iter()
.cloned()
.map(|x| x.into())
.collect()
}
};
let named_export = &*(func as *mut NamedExport);

View File

@ -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() {}

Binary file not shown.

View File

@ -2,84 +2,443 @@
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>
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);
wasmer_export_t *export = wasmer_exports_get(exports, 0);
{
printf("\nCheck the `sum` exported function\n");
wasmer_import_export_kind kind = wasmer_export_kind(export);
assert(kind == WASM_FUNCTION);
const wasmer_export_func_t *func = wasmer_export_to_func(export);
wasmer_export_t *export = wasmer_exports_get(exports, 3);
wasmer_import_export_kind export_kind = wasmer_export_kind(export);
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]);
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 == sizeof("sum") - 1);
assert(memcmp(name_bytes.bytes, "sum", sizeof("sum") - 1) == 0);
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 *) calloc(inputs_arity, sizeof(wasmer_value_tag));
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
wasmer_export_func_returns(exported_function, output_types, outputs_arity);
assert(output_types[0] == WASM_I32);
free(output_types);
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, &params_arity);
assert(params_arity == 2);
{
printf("\nCheck the `arity_0` exported function\n");
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);
wasmer_export_t *export = wasmer_exports_get(exports, 4);
wasmer_import_export_kind export_kind = wasmer_export_kind(export);
uint32_t returns_arity;
wasmer_export_func_returns_arity(func, &returns_arity);
assert(returns_arity == 1);
assert(export_kind == WASM_FUNCTION);
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);
const wasmer_export_func_t *exported_function = wasmer_export_to_func(export);
wasmer_byte_array name_bytes = wasmer_export_name(export);
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};
assert(name_bytes.bytes_len == sizeof("arity_0") - 1);
assert(memcmp(name_bytes.bytes, "arity_0", sizeof("arity_0") - 1) == 0);
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);
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("i32_i32") - 1);
assert(memcmp(name_bytes.bytes, "i32_i32", sizeof("i32_i32") - 1) == 0);
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 *) calloc(inputs_arity, sizeof(wasmer_value_tag));
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("i64_i64") - 1);
assert(memcmp(name_bytes.bytes, "i64_i64", sizeof("i64_i64") - 1) == 0);
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 *) calloc(inputs_arity, sizeof(wasmer_value_tag));
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("f32_f32") - 1);
assert(memcmp(name_bytes.bytes, "f32_f32", sizeof("f32_f32") - 1) == 0);
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 *) calloc(inputs_arity, sizeof(wasmer_value_tag));
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("f64_f64") - 1);
assert(memcmp(name_bytes.bytes, "f64_f64", sizeof("f64_f64") - 1) == 0);
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 *) calloc(inputs_arity, sizeof(wasmer_value_tag));
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("string") - 1);
assert(memcmp(name_bytes.bytes, "string", sizeof("string") - 1) == 0);
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 *) calloc(outputs_arity, sizeof(wasmer_value_tag));
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 == sizeof("void") - 1);
assert(memcmp(name_bytes.bytes, "void", sizeof("void") - 1) == 0);
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");
printf("Destroy instance\n");
wasmer_instance_destroy(instance);
printf("Destroy exports\n");
wasmer_exports_destroy(exports);
return 0;
}

View File

@ -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.
*/

View File

@ -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);