Skip to content

Commit

Permalink
Merge #296
Browse files Browse the repository at this point in the history
296: feat(runtime-c-api) Implement the `wasmer_export_to_memory` function r=Hywan a=Hywan

This new function returns a `wasmer_memory_t` from a `wasmer_export_t`. It allows to use the `wasmer_memory_*` API over the exported memories from a Wasm instance.

See `tests/assets/return_hello.rs` and `tests/test-exported-memory.c` for an end-to-end example.

This PR also moves all `tests/.wasm` files into `tests/assets/`. I've added the source of `return_hello.wasm` to be exhaustive and to serve as a documentation.

Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
  • Loading branch information
bors[bot] and Hywan committed Mar 27, 2019
2 parents cb35057 + a59ce13 commit f249d3a
Show file tree
Hide file tree
Showing 20 changed files with 149 additions and 25 deletions.
35 changes: 31 additions & 4 deletions lib/runtime-c-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate wasmer_runtime;
extern crate wasmer_runtime_core;

use libc::{c_char, c_int, int32_t, int64_t, uint32_t, uint8_t};
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::error::Error;
use std::ffi::CStr;
Expand Down Expand Up @@ -1409,6 +1409,34 @@ pub unsafe extern "C" fn wasmer_export_to_func(
export as *const wasmer_export_func_t
}

/// 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.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_export_to_memory(
export: *const wasmer_export_t,
memory: *mut *mut wasmer_memory_t,
) -> wasmer_result_t {
let named_export = &*(export as *const NamedExport);
let export = &named_export.export;

if let Export::Memory(exported_memory) = export {
*memory = exported_memory as *const Memory as *mut wasmer_memory_t;
wasmer_result_t::WASMER_OK
} else {
update_last_error(CApiError {
msg: "cannot cast the `wasmer_export_t` pointer to a `wasmer_memory_t` \
pointer because it does not represent a memory export."
.to_string(),
});
wasmer_result_t::WASMER_ERROR
}
}

/// Gets name from wasmer_export
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
Expand Down Expand Up @@ -1517,9 +1545,8 @@ pub extern "C" fn wasmer_instance_context_data_get(
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_memory_data(mem: *const wasmer_memory_t) -> *mut uint8_t {
let memory = mem as *const Memory;
use std::cell::Cell;
unsafe { ((*memory).view::<u8>()[..]).as_ptr() as *mut Cell<u8> as *mut u8 }
let memory = unsafe { &*(mem as *const Memory) };
memory.view::<u8>()[..].as_ptr() as *mut Cell<u8> as *mut u8
}

/// Gets the size in bytes of a Memory
Expand Down
1 change: 1 addition & 0 deletions lib/runtime-c-api/tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ compile_commands.json
CTestTestfile.cmake
_deps
rust-build
test-exported-memory
test-exports
test-globals
test-import-function
Expand Down
5 changes: 5 additions & 0 deletions lib/runtime-c-api/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cmake_minimum_required (VERSION 2.6)
project (WasmerRuntimeCApiTests)

add_executable(test-exported-memory test-exported-memory.c)
add_executable(test-exports test-exports.c)
add_executable(test-globals test-globals.c)
add_executable(test-import-function test-import-function.c)
Expand Down Expand Up @@ -35,6 +36,10 @@ set(
"/WX" >
)

target_link_libraries(test-exported-memory general ${WASMER_LIB})
target_compile_options(test-exported-memory PRIVATE ${COMPILER_OPTIONS})
add_test(test-exported-memory test-exported-memory)

target_link_libraries(test-exports general ${WASMER_LIB})
target_compile_options(test-exports PRIVATE ${COMPILER_OPTIONS})
add_test(test-exports test-exports)
Expand Down
File renamed without changes.
4 changes: 4 additions & 0 deletions lib/runtime-c-api/tests/assets/return_hello.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[no_mangle]
pub extern "C" fn return_hello() -> *const u8 {
b"Hello, World!\0"[..].as_ptr()
}
Binary file added lib/runtime-c-api/tests/assets/return_hello.wasm
Binary file not shown.
File renamed without changes.
73 changes: 73 additions & 0 deletions lib/runtime-c-api/tests/test-exported-memory.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <stdio.h>
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>

int main()
{
// Read the wasm file bytes
FILE *file = fopen("assets/return_hello.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);

// Instantiate the module.
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);
assert(compile_result == WASMER_OK);

// Call the `return_hello` function.
wasmer_value_t params[] = {};
wasmer_value_t result;
wasmer_value_t results[] = {result};

wasmer_result_t call_result = wasmer_instance_call(instance, "return_hello", params, 0, results, 1);
printf("Call result: %d\n", call_result);
printf("Result: %d\n", results[0].value.I32);
assert(call_result == WASMER_OK);
assert(results[0].value.I32 == 1048576);

// Get all exports.
wasmer_exports_t *exports = NULL;
wasmer_instance_exports(instance, &exports);

int export_length = wasmer_exports_len(exports);
printf("exports_length: %d\n", export_length);
assert(export_length == 5);

// Get the `memory` export.
wasmer_export_t *export = wasmer_exports_get(exports, 1);
wasmer_import_export_kind kind = wasmer_export_kind(export);
assert(kind == WASM_MEMORY);

wasmer_byte_array export_name = wasmer_export_name(export);
printf("export_name: `%.*s`\n", export_name.bytes_len, export_name.bytes);

// Cast the export into a memory.
wasmer_memory_t *memory;
wasmer_result_t export_to_memory_result = wasmer_export_to_memory(export, &memory);
printf("Export to memory result: %d\n", export_to_memory_result);
printf("Memory pointer: %p\n", memory);
assert(export_to_memory_result == WASMER_OK);

uint32_t memory_length = wasmer_memory_length(memory);
assert(memory_length == 17);

// Read the data from the memory.
uint8_t *memory_data = wasmer_memory_data(memory);
uint8_t *returned_string = memory_data + results[0].value.I32;

printf("Returned string from Wasm: %s\n", returned_string);
assert(strcmp("Hello, World!", (const char *) returned_string) == 0);

printf("Destroy instance\n");
wasmer_instance_destroy(instance);

return 0;
}
6 changes: 3 additions & 3 deletions lib/runtime-c-api/tests/test-exports.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand All @@ -17,14 +17,14 @@ int main()
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);
printf("Compile result: %d\n", compile_result);
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);
printf("exports_len: %d\n", exports_len);
assert(exports_len == 1);

wasmer_export_t *export = wasmer_exports_get(exports, 0);
Expand Down
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-import-function.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int main()
wasmer_import_t imports[] = {import};

// Read the wasm file bytes
FILE *file = fopen("wasm_sample_app.wasm", "r");
FILE *file = fopen("assets/wasm_sample_app.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-imports.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ int main()
wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import};

// Read the wasm file bytes
FILE *file = fopen("hello_wasm.wasm", "r");
FILE *file = fopen("assets/hello_wasm.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-instantiate.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
4 changes: 2 additions & 2 deletions lib/runtime-c-api/tests/test-module-exports.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down Expand Up @@ -50,4 +50,4 @@ int main()
printf("Destroy exports\n");
wasmer_export_descriptors_destroy(exports);
return 0;
}
}
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-module-imports.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("wasm_sample_app.wasm", "r");
FILE *file = fopen("assets/wasm_sample_app.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-module-serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
4 changes: 2 additions & 2 deletions lib/runtime-c-api/tests/test-module.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down Expand Up @@ -48,4 +48,4 @@ int main()
printf("Destroy module\n");
wasmer_module_destroy(module);
return 0;
}
}
2 changes: 1 addition & 1 deletion lib/runtime-c-api/tests/test-validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
int main()
{
// Read the wasm file bytes
FILE *file = fopen("sum.wasm", "r");
FILE *file = fopen("assets/sum.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
Expand Down
16 changes: 12 additions & 4 deletions lib/runtime-c-api/wasmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ typedef struct {

typedef struct {

} wasmer_memory_t;

typedef struct {

} wasmer_exports_t;

typedef struct {
Expand Down Expand Up @@ -99,10 +103,6 @@ typedef struct {

typedef struct {

} wasmer_memory_t;

typedef struct {

} wasmer_table_t;

typedef union {
Expand Down Expand Up @@ -241,6 +241,14 @@ 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);

/**
* Frees the memory for the given exports
*/
Expand Down
14 changes: 10 additions & 4 deletions lib/runtime-c-api/wasmer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ struct wasmer_export_t {

};

struct wasmer_memory_t {

};

struct wasmer_exports_t {

};
Expand Down Expand Up @@ -94,10 +98,6 @@ struct wasmer_instance_context_t {

};

struct wasmer_memory_t {

};

struct wasmer_table_t {

};
Expand Down Expand Up @@ -210,6 +210,12 @@ wasmer_byte_array wasmer_export_name(wasmer_export_t *export_);
/// Gets export func from 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);

/// Frees the memory for the given exports
void wasmer_exports_destroy(wasmer_exports_t *exports);

Expand Down

0 comments on commit f249d3a

Please sign in to comment.