diff --git a/lib/runtime-c-api/src/instance.rs b/lib/runtime-c-api/src/instance.rs index 5a1f8719a..44b5ccafc 100644 --- a/lib/runtime-c-api/src/instance.rs +++ b/lib/runtime-c-api/src/instance.rs @@ -108,6 +108,18 @@ pub unsafe extern "C" fn wasmer_instantiate( wasmer_result_t::WASMER_OK } +#[allow(clippy::cast_ptr_alignment)] +#[no_mangle] +pub unsafe extern "C" fn wasmer_instance_context_get( + instance: *mut wasmer_instance_t, +) -> *const wasmer_instance_context_t { + let instance_ref = &*(instance as *const Instance); + + let ctx: *const Ctx = instance_ref.context() as *const _; + + ctx as *const wasmer_instance_context_t +} + /// Calls an instances exported function by `name` with the provided parameters. /// Results are set using the provided `results` pointer. /// diff --git a/lib/runtime-c-api/tests/CMakeLists.txt b/lib/runtime-c-api/tests/CMakeLists.txt index 6e636a6a0..c9e13dafc 100644 --- a/lib/runtime-c-api/tests/CMakeLists.txt +++ b/lib/runtime-c-api/tests/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(test-module-imports test-module-imports.c) add_executable(test-module-serialize test-module-serialize.c) add_executable(test-tables test-tables.c) add_executable(test-validate test-validate.c) +add_executable(test-context test-context.c) find_library( WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so libwasmer_runtime_c_api.dll @@ -87,3 +88,7 @@ add_test(test-tables test-tables) target_link_libraries(test-validate general ${WASMER_LIB}) target_compile_options(test-validate PRIVATE ${COMPILER_OPTIONS}) add_test(test-validate test-validate) + +target_link_libraries(test-context general ${WASMER_LIB}) +target_compile_options(test-context PRIVATE ${COMPILER_OPTIONS}) +add_test(test-context test-context) diff --git a/lib/runtime-c-api/tests/assets/inc.wasm b/lib/runtime-c-api/tests/assets/inc.wasm new file mode 100644 index 000000000..d7a66c10e Binary files /dev/null and b/lib/runtime-c-api/tests/assets/inc.wasm differ diff --git a/lib/runtime-c-api/tests/assets/inc.wast b/lib/runtime-c-api/tests/assets/inc.wast new file mode 100644 index 000000000..4b5e58c9f --- /dev/null +++ b/lib/runtime-c-api/tests/assets/inc.wast @@ -0,0 +1,7 @@ +(module + (func $inc (import "env" "inc")) + (func $get (import "env" "get") (result i32)) + + (func (export "inc_and_get") (result i32) + call $inc + call $get)) diff --git a/lib/runtime-c-api/tests/test-context.c b/lib/runtime-c-api/tests/test-context.c new file mode 100644 index 000000000..cc8bfcef5 --- /dev/null +++ b/lib/runtime-c-api/tests/test-context.c @@ -0,0 +1,83 @@ +#include +#include "../wasmer.h" +#include +#include +#include + +typedef struct { + int32_t amount; + int32_t value; +} counter_data; + +void inc_counter(wasmer_instance_context_t *ctx) { + counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx); + data->value = data->value + data->amount; +} + +int32_t get_counter(wasmer_instance_context_t *ctx) { + counter_data* data = (counter_data*)wasmer_instance_context_data_get(ctx); + return data->value; +} + +wasmer_import_t create_import(char* module_name, char* import_name, wasmer_import_func_t *func) { + wasmer_import_t import; + wasmer_byte_array module_name_bytes; + wasmer_byte_array import_name_bytes; + + module_name_bytes.bytes = (const uint8_t *) module_name; + module_name_bytes.bytes_len = strlen(module_name); + + import_name_bytes.bytes = (const uint8_t *) import_name; + import_name_bytes.bytes_len = strlen(import_name); + + import.module_name = module_name_bytes; + import.import_name = import_name_bytes; + + import.tag = WASM_FUNCTION; + import.value.func = func; + + return import; +} + +int main() +{ + // Imports + wasmer_value_tag inc_params_sig[] = {}; + wasmer_value_tag inc_returns_sig[] = {}; + wasmer_import_func_t *inc_func = wasmer_import_func_new((void (*)(void *)) inc_counter, inc_params_sig, 0, inc_returns_sig, 0); + wasmer_import_t inc_import = create_import("env", "inc", inc_func); + + wasmer_value_tag get_params_sig[] = {}; + wasmer_value_tag get_returns_sig[] = {WASM_I32}; + wasmer_import_func_t *get_func = wasmer_import_func_new((void (*)(void *)) get_counter, get_params_sig, 0, get_returns_sig, 1); + wasmer_import_t get_import = create_import("env", "get", get_func); + + wasmer_import_t imports[] = {inc_import, get_import}; + + // Read the wasm file bytes + FILE *file = fopen("assets/inc.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); + + printf("Instantiating\n"); + wasmer_instance_t *instance = NULL; + wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 2); + printf("Compile result: %d\n", compile_result); + + counter_data* counter = malloc(sizeof(counter_data)); + counter->value = 0; + counter->amount = 5; + wasmer_instance_context_data_set(instance, counter); + + wasmer_result_t call1_result = wasmer_instance_call(instance, "inc_and_get", NULL, 0, NULL, 0); + printf("Call result: %d\n", call1_result); + + wasmer_result_t call2_result = wasmer_instance_call(instance, "inc_and_get", NULL, 0, NULL, 0); + printf("Call result: %d\n", call2_result); + + return 0; +} diff --git a/lib/runtime-c-api/wasmer.h b/lib/runtime-c-api/wasmer.h index 7c0f5249a..ad6259efe 100644 --- a/lib/runtime-c-api/wasmer.h +++ b/lib/runtime-c-api/wasmer.h @@ -417,6 +417,8 @@ void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); */ void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); +const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance); + /** * Gets the memory within the context at the index `memory_idx`. * The index is always 0 until multiple memories are supported. diff --git a/lib/runtime-c-api/wasmer.hh b/lib/runtime-c-api/wasmer.hh index 1c00b74c3..a86a901f3 100644 --- a/lib/runtime-c-api/wasmer.hh +++ b/lib/runtime-c-api/wasmer.hh @@ -337,6 +337,8 @@ void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); /// passed to all imported function for instance. void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); +const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance); + /// Gets the memory within the context at the index `memory_idx`. /// The index is always 0 until multiple memories are supported. const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx,