diff --git a/lib/runtime-c-api/src/lib.rs b/lib/runtime-c-api/src/lib.rs index e6e82dc0d..1931656e7 100644 --- a/lib/runtime-c-api/src/lib.rs +++ b/lib/runtime-c-api/src/lib.rs @@ -131,6 +131,12 @@ pub union wasmer_import_export_value { global: *const wasmer_global_t, } +#[repr(C)] +pub struct wasmer_byte_array { + bytes: *const uint8_t, + bytes_len: uint32_t, +} + /// Returns true for valid wasm bytes and false for invalid bytes #[allow(clippy::cast_ptr_alignment)] #[no_mangle] @@ -557,6 +563,101 @@ pub unsafe extern "C" fn wasmer_export_kind( } } +/// Gets func from wasm_export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_to_func( + export: *mut wasmer_export_t, +) -> *const wasmer_func_t { + let named_export = &*(export as *mut NamedExport); + &named_export.export as *const Export as *const wasmer_func_t +} + +/// Gets name from wasmer_export +#[no_mangle] +#[allow(clippy::cast_ptr_alignment)] +pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) -> wasmer_byte_array { + let named_export = &*(export as *mut NamedExport); + wasmer_byte_array { + bytes: named_export.name.as_ptr(), + bytes_len: named_export.name.len() as u32, + } +} + +/// 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. +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_func_call( + func: *mut wasmer_func_t, + params: *const wasmer_value_t, + params_len: c_int, + results: *mut wasmer_value_t, + results_len: c_int, +) -> wasmer_result_t { + if func.is_null() { + update_last_error(CApiError { + msg: "func ptr is null".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + } + if 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 export_func = unsafe { Box::from_raw(func as *mut Export) }; + + let results: &mut [wasmer_value_t] = slice::from_raw_parts_mut(results, results_len as usize); + // TODO implement func.call + update_last_error(CApiError { + msg: "wasmer_func_call not yet implemented".to_string(), + }); + return wasmer_result_t::WASMER_ERROR; + // let result = instance.call(func_name_r, ¶ms[..]); + // Box::into_raw(export_func); + // match result { + // Ok(results_vec) => { + // if results_vec.len() > 0 { + // let ret = match results_vec[0] { + // Value::I32(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_I32, + // value: wasmer_value { I32: x }, + // }, + // Value::I64(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_I64, + // value: wasmer_value { I64: x }, + // }, + // Value::F32(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_F32, + // value: wasmer_value { F32: x }, + // }, + // Value::F64(x) => wasmer_value_t { + // tag: wasmer_value_tag::WASM_F64, + // value: wasmer_value { F64: x }, + // }, + // }; + // results[0] = ret; + // } + // wasmer_result_t::WASMER_OK + // } + // Err(err) => { + // update_last_error(err); + // wasmer_result_t::WASMER_ERROR + // } + // } +} + ///// Gets wasmer_export func //#[no_mangle] //pub unsafe extern "C" fn wasmer_export_name(export: *mut wasmer_export_t) { diff --git a/lib/runtime-c-api/tests/test-exports.c b/lib/runtime-c-api/tests/test-exports.c index 8516d562b..b00adb790 100644 --- a/lib/runtime-c-api/tests/test-exports.c +++ b/lib/runtime-c-api/tests/test-exports.c @@ -32,6 +32,32 @@ int main() wasmer_import_export_kind kind = wasmer_export_kind(export); assert(kind == WASM_FUNCTION); + wasmer_func_t *func = 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'}; + for(int idx = 0; idx < 3; idx++){ + printf("%c\n", name_bytes.bytes[idx]); + assert(name_bytes.bytes[idx] == expected[idx]); + } + +// 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_func_call(func, params, 2, results, 1); +// printf("Call result: %d\n", call_result); +// printf("Result: %d\n", results[0].value.I32); +// assert(results[0].value.I32 == 15); +// assert(call_result == WASMER_OK); + printf("Destroy instance\n"); wasmer_instance_destroy(instance); diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 86230de1c..f55014bee 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -38,12 +38,17 @@ typedef struct { } wasmer_export_t; typedef struct { - -} wasmer_exports_t; + const uint8_t *bytes; + uint32_t bytes_len; +} wasmer_byte_array; typedef struct { -} wasmer_global_t; +} wasmer_func_t; + +typedef struct { + +} wasmer_exports_t; typedef union { int32_t I32; @@ -57,6 +62,10 @@ typedef struct { wasmer_value value; } wasmer_value_t; +typedef struct { + +} wasmer_global_t; + typedef struct { bool mutable_; wasmer_value_tag kind; @@ -80,6 +89,16 @@ typedef struct { */ wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); +/** + * Gets func from wasm_export + */ +wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); + +/** + * Gets func from wasm_export + */ +const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); + /** * Frees the memory for the given exports */ @@ -95,6 +114,19 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); */ int wasmer_exports_len(wasmer_exports_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_func_call(wasmer_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + /** * Frees memory for the given Global */ diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 32b6e435f..02de6f52b 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -34,11 +34,16 @@ struct wasmer_export_t { }; -struct wasmer_exports_t { +struct wasmer_byte_array { + const uint8_t *bytes; + uint32_t bytes_len; +}; + +struct wasmer_func_t { }; -struct wasmer_global_t { +struct wasmer_exports_t { }; @@ -54,6 +59,10 @@ struct wasmer_value_t { wasmer_value value; }; +struct wasmer_global_t { + +}; + struct wasmer_global_descriptor_t { bool mutable_; wasmer_value_tag kind; @@ -77,6 +86,12 @@ extern "C" { /// Gets wasmer_export kind wasmer_import_export_kind wasmer_export_kind(wasmer_export_t *export_); +/// Gets func from wasm_export +wasmer_byte_array wasmer_export_name(wasmer_export_t *export_); + +/// Gets func from wasm_export +const wasmer_func_t *wasmer_export_to_func(wasmer_export_t *export_); + /// Frees the memory for the given exports void wasmer_exports_destroy(wasmer_exports_t *exports); @@ -86,6 +101,17 @@ wasmer_export_t *wasmer_exports_get(wasmer_exports_t *exports, int idx); /// Gets the length of the exports int wasmer_exports_len(wasmer_exports_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_func_call(wasmer_func_t *func, + const wasmer_value_t *params, + int params_len, + wasmer_value_t *results, + int results_len); + /// Frees memory for the given Global void wasmer_global_destroy(wasmer_global_t *global);