mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 13:41:32 +00:00
Update Emscripten API layout; expose inner parts to to C API; add test
This commit is contained in:
@ -325,6 +325,61 @@ impl<'a> EmscriptenData<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Call the global constructors for C++ and set up the emscripten environment.
|
||||
///
|
||||
/// Note that this function does not completely set up Emscripten to be called.
|
||||
/// before calling this function, please initialize `Ctx::data` with a pointer
|
||||
/// to [`EmscriptenData`].
|
||||
pub fn set_up_emscripten(instance: &mut Instance) -> CallResult<()> {
|
||||
// ATINIT
|
||||
// (used by C++)
|
||||
if let Ok(_func) = instance.dyn_func("globalCtors") {
|
||||
instance.call("globalCtors", &[])?;
|
||||
}
|
||||
|
||||
if let Ok(_func) = instance.dyn_func("___emscripten_environ_constructor") {
|
||||
instance.call("___emscripten_environ_constructor", &[])?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Call the main function in emscripten, assumes that the emscripten state is
|
||||
/// set up.
|
||||
///
|
||||
/// If you don't want to set it up yourself, consider using [`run_emscripten_instance`].
|
||||
pub fn emscripten_call_main(instance: &mut Instance, path: &str, args: &[&str]) -> CallResult<()> {
|
||||
let (func_name, main_func) = match instance.dyn_func("_main") {
|
||||
Ok(func) => Ok(("_main", func)),
|
||||
Err(_e) => match instance.dyn_func("main") {
|
||||
Ok(func) => Ok(("main", func)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
}?;
|
||||
let num_params = main_func.signature().params().len();
|
||||
let _result = match num_params {
|
||||
2 => {
|
||||
let mut new_args = vec![path];
|
||||
new_args.extend(args);
|
||||
let (argc, argv) = store_module_arguments(instance.context_mut(), new_args);
|
||||
instance.call(
|
||||
func_name,
|
||||
&[Value::I32(argc as i32), Value::I32(argv as i32)],
|
||||
)?;
|
||||
}
|
||||
0 => {
|
||||
instance.call(func_name, &[])?;
|
||||
}
|
||||
_ => {
|
||||
return Err(CallError::Resolve(ResolveError::ExportWrongType {
|
||||
name: "main".to_string(),
|
||||
}))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Top level function to execute emscripten
|
||||
pub fn run_emscripten_instance(
|
||||
_module: &Module,
|
||||
instance: &mut Instance,
|
||||
@ -338,15 +393,7 @@ pub fn run_emscripten_instance(
|
||||
let data_ptr = &mut data as *mut _ as *mut c_void;
|
||||
instance.context_mut().data = data_ptr;
|
||||
|
||||
// ATINIT
|
||||
// (used by C++)
|
||||
if let Ok(_func) = instance.dyn_func("globalCtors") {
|
||||
instance.call("globalCtors", &[])?;
|
||||
}
|
||||
|
||||
if let Ok(_func) = instance.dyn_func("___emscripten_environ_constructor") {
|
||||
instance.call("___emscripten_environ_constructor", &[])?;
|
||||
}
|
||||
set_up_emscripten(instance)?;
|
||||
|
||||
// println!("running emscripten instance");
|
||||
|
||||
@ -356,33 +403,7 @@ pub fn run_emscripten_instance(
|
||||
//let (argc, argv) = store_module_arguments(instance.context_mut(), args);
|
||||
instance.call(&ep, &[Value::I32(arg as i32)])?;
|
||||
} else {
|
||||
let (func_name, main_func) = match instance.dyn_func("_main") {
|
||||
Ok(func) => Ok(("_main", func)),
|
||||
Err(_e) => match instance.dyn_func("main") {
|
||||
Ok(func) => Ok(("main", func)),
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
}?;
|
||||
let num_params = main_func.signature().params().len();
|
||||
let _result = match num_params {
|
||||
2 => {
|
||||
let mut new_args = vec![path];
|
||||
new_args.extend(args);
|
||||
let (argc, argv) = store_module_arguments(instance.context_mut(), new_args);
|
||||
instance.call(
|
||||
func_name,
|
||||
&[Value::I32(argc as i32), Value::I32(argv as i32)],
|
||||
)?;
|
||||
}
|
||||
0 => {
|
||||
instance.call(func_name, &[])?;
|
||||
}
|
||||
_ => {
|
||||
return Err(CallError::Resolve(ResolveError::ExportWrongType {
|
||||
name: "main".to_string(),
|
||||
}))
|
||||
}
|
||||
};
|
||||
emscripten_call_main(instance, path, &args)?;
|
||||
}
|
||||
|
||||
// TODO atexit for emscripten
|
||||
|
@ -1,10 +1,11 @@
|
||||
//! Functions and types for dealing with Emscripten imports
|
||||
|
||||
use super::*;
|
||||
use crate::module::wasmer_module_t;
|
||||
use crate::{get_slice_checked, instance::wasmer_instance_t, module::wasmer_module_t};
|
||||
|
||||
use std::ptr;
|
||||
use wasmer_emscripten::EmscriptenGlobals;
|
||||
use wasmer_runtime::Module;
|
||||
use wasmer_runtime::{Instance, Module};
|
||||
|
||||
/// Type used to construct an import_object_t with Emscripten imports.
|
||||
#[repr(C)]
|
||||
@ -40,9 +41,88 @@ pub unsafe extern "C" fn wasmer_emscripten_destroy_emscripten_globals(
|
||||
let _ = Box::from_raw(globals);
|
||||
}
|
||||
|
||||
/// Execute global constructors (required if the module is compiled from C++)
|
||||
/// and sets up the internal environment.
|
||||
///
|
||||
/// This function sets the data pointer in the same way that
|
||||
/// [`wasmer_instance_context_data_set`] does.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_emscripten_set_up_emscripten(
|
||||
instance: *mut wasmer_instance_t,
|
||||
globals: *mut wasmer_emscripten_globals_t,
|
||||
) -> wasmer_result_t {
|
||||
if globals.is_null() || instance.is_null() {
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
}
|
||||
let instance = &mut *(instance as *mut Instance);
|
||||
instance.context_mut().data = globals as *mut c_void;
|
||||
match wasmer_emscripten::set_up_emscripten(instance) {
|
||||
Ok(_) => wasmer_result_t::WASMER_OK,
|
||||
Err(e) => {
|
||||
update_last_error(e);
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience function for setting up arguments and calling the Emscripten
|
||||
/// main function.
|
||||
///
|
||||
/// WARNING:
|
||||
///
|
||||
/// Do not call this function on untrusted code when operating without
|
||||
/// additional sandboxing in place.
|
||||
/// Emscripten has access to many host system calls and therefore may do very
|
||||
/// bad things.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_emscripten_call_main(
|
||||
instance: *mut wasmer_instance_t,
|
||||
args: *const wasmer_byte_array,
|
||||
args_len: c_uint,
|
||||
) -> wasmer_result_t {
|
||||
if instance.is_null() || args.is_null() {
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
}
|
||||
let instance = &mut *(instance as *mut Instance);
|
||||
|
||||
let arg_list = get_slice_checked(args, args_len as usize);
|
||||
let arg_process_result: Result<Vec<&str>, _> =
|
||||
arg_list.iter().map(|arg| arg.as_str()).collect();
|
||||
let arg_vec = match arg_process_result.as_ref() {
|
||||
Ok(arg_vec) => arg_vec,
|
||||
Err(err) => {
|
||||
update_last_error(*err);
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
let prog_name = if let Some(prog_name) = arg_vec.first() {
|
||||
prog_name
|
||||
} else {
|
||||
update_last_error(CApiError {
|
||||
msg: "First argument (program name) is required to execute Emscripten's main function"
|
||||
.to_string(),
|
||||
});
|
||||
return wasmer_result_t::WASMER_ERROR;
|
||||
};
|
||||
|
||||
match wasmer_emscripten::emscripten_call_main(instance, prog_name, &arg_vec[1..]) {
|
||||
Ok(_) => wasmer_result_t::WASMER_OK,
|
||||
Err(e) => {
|
||||
update_last_error(e);
|
||||
wasmer_result_t::WASMER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `wasmer_import_object_t` with Emscripten imports, use
|
||||
/// `wasmer_emscripten_get_emscripten_globals` to get a
|
||||
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
|
||||
///
|
||||
/// WARNING:
|
||||
///1
|
||||
/// This `import_object_t` contains thin-wrappers around host system calls.
|
||||
/// Do not use this to execute untrusted code without additional sandboxing.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wasmer_emscripten_generate_import_object(
|
||||
globals: *mut wasmer_emscripten_globals_t,
|
||||
|
3
lib/runtime-c-api/tests/.gitignore
vendored
3
lib/runtime-c-api/tests/.gitignore
vendored
@ -26,4 +26,5 @@ test-module-imports
|
||||
test-module-serialize
|
||||
test-tables
|
||||
test-validate
|
||||
test-wasi-import-object
|
||||
test-wasi-import-object
|
||||
test-emscripten-import-object
|
@ -22,6 +22,11 @@ if (DEFINED WASI_TESTS)
|
||||
add_executable(test-wasi-import-object test-wasi-import-object.c)
|
||||
endif()
|
||||
|
||||
if (DEFINED EMSCRIPTEN_TESTS)
|
||||
add_executable(test-emscripten-import-object test-emscripten-import-object.c)
|
||||
endif()
|
||||
|
||||
|
||||
find_library(
|
||||
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so wasmer_runtime_c_api.dll
|
||||
PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/
|
||||
@ -74,6 +79,12 @@ if (DEFINED WASI_TESTS)
|
||||
add_test(test-wasi-import-object test-wasi-import-object)
|
||||
endif()
|
||||
|
||||
if (DEFINED EMSCRIPTEN_TESTS)
|
||||
target_link_libraries(test-emscripten-import-object general ${WASMER_LIB})
|
||||
target_compile_options(test-emscripten-import-object PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-emscripten-import-object test-emscripten-import-object)
|
||||
endif()
|
||||
|
||||
target_link_libraries(test-instantiate general ${WASMER_LIB})
|
||||
target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS})
|
||||
add_test(test-instantiate test-instantiate)
|
||||
|
10
lib/runtime-c-api/tests/assets/emscripten_hello_world.c
Normal file
10
lib/runtime-c-api/tests/assets/emscripten_hello_world.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("Hello, world\n");
|
||||
for ( int i = 0; i < argc; ++i ) {
|
||||
printf("Arg %d: '%s'\n", i, argv[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
BIN
lib/runtime-c-api/tests/assets/emscripten_hello_world.wasm
Normal file
BIN
lib/runtime-c-api/tests/assets/emscripten_hello_world.wasm
Normal file
Binary file not shown.
@ -8,8 +8,10 @@ fn test_c_api() {
|
||||
".",
|
||||
#[cfg(feature = "wasi")]
|
||||
"-DWASI_TESTS=ON",
|
||||
#[cfg(feature = "emscripten")]
|
||||
"-DEMSCRIPTEN_TESTS=ON",
|
||||
];
|
||||
// we use -f so it doesn't fail if the fiel doesn't exist
|
||||
// we use -f so it doesn't fail if the file doesn't exist
|
||||
run_command("rm", project_tests_dir, vec!["-f", "CMakeCache.txt"]);
|
||||
run_command("cmake", project_tests_dir, cmake_args);
|
||||
run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]);
|
||||
|
235
lib/runtime-c-api/tests/test-emscripten-import-object.c
Normal file
235
lib/runtime-c-api/tests/test-emscripten-import-object.c
Normal file
@ -0,0 +1,235 @@
|
||||
#include <stdio.h>
|
||||
#include "../wasmer.h"
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool host_print_called = false;
|
||||
|
||||
// Host function that will be imported into the Web Assembly Instance
|
||||
void host_print(const wasmer_instance_context_t *ctx, int32_t ptr, int32_t len)
|
||||
{
|
||||
host_print_called = true;
|
||||
const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0);
|
||||
uint32_t mem_len = wasmer_memory_length(memory);
|
||||
uint8_t *mem_bytes = wasmer_memory_data(memory);
|
||||
printf("%.*s", len, mem_bytes + ptr);
|
||||
}
|
||||
|
||||
// Use the last_error API to retrieve error messages
|
||||
void print_wasmer_error()
|
||||
{
|
||||
int error_len = wasmer_last_error_length();
|
||||
printf("Error len: `%d`\n", error_len);
|
||||
char *error_str = malloc(error_len);
|
||||
wasmer_last_error_message(error_str, error_len);
|
||||
printf("Error str: `%s`\n", error_str);
|
||||
}
|
||||
|
||||
// helper function to print byte array to stdout
|
||||
void print_byte_array(wasmer_byte_array *arr) {
|
||||
for (int i = 0; i < arr->bytes_len; ++i) {
|
||||
putchar(arr->bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Create a new func to hold the parameter and signature
|
||||
// of our `host_print` host function
|
||||
wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32};
|
||||
wasmer_value_tag returns_sig[] = {};
|
||||
wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) host_print, params_sig, 2, returns_sig, 0);
|
||||
|
||||
// Create module name for our imports
|
||||
// represented in bytes for UTF-8 compatability
|
||||
const char *module_name = "env";
|
||||
wasmer_byte_array module_name_bytes;
|
||||
module_name_bytes.bytes = (const uint8_t *) module_name;
|
||||
module_name_bytes.bytes_len = strlen(module_name);
|
||||
|
||||
// Define a function import
|
||||
const char *import_name = "host_print";
|
||||
wasmer_byte_array import_name_bytes;
|
||||
import_name_bytes.bytes = (const uint8_t *) import_name;
|
||||
import_name_bytes.bytes_len = strlen(import_name);
|
||||
wasmer_import_t func_import;
|
||||
func_import.module_name = module_name_bytes;
|
||||
func_import.import_name = import_name_bytes;
|
||||
func_import.tag = WASM_FUNCTION;
|
||||
func_import.value.func = func;
|
||||
|
||||
// Define a memory import
|
||||
const char *import_memory_name = "memory";
|
||||
wasmer_byte_array import_memory_name_bytes;
|
||||
import_memory_name_bytes.bytes = (const uint8_t *) import_memory_name;
|
||||
import_memory_name_bytes.bytes_len = strlen(import_memory_name);
|
||||
wasmer_import_t memory_import;
|
||||
memory_import.module_name = module_name_bytes;
|
||||
memory_import.import_name = import_memory_name_bytes;
|
||||
memory_import.tag = WASM_MEMORY;
|
||||
wasmer_memory_t *memory = NULL;
|
||||
wasmer_limits_t descriptor;
|
||||
descriptor.min = 256;
|
||||
wasmer_limit_option_t max;
|
||||
max.has_some = true;
|
||||
max.some = 256;
|
||||
descriptor.max = max;
|
||||
wasmer_result_t memory_result = wasmer_memory_new(&memory, descriptor);
|
||||
if (memory_result != WASMER_OK)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
memory_import.value.memory = memory;
|
||||
|
||||
// Define a global import
|
||||
const char *import_global_name = "__memory_base";
|
||||
wasmer_byte_array import_global_name_bytes;
|
||||
import_global_name_bytes.bytes = (const uint8_t *) import_global_name;
|
||||
import_global_name_bytes.bytes_len = strlen(import_global_name);
|
||||
wasmer_import_t global_import;
|
||||
global_import.module_name = module_name_bytes;
|
||||
global_import.import_name = import_global_name_bytes;
|
||||
global_import.tag = WASM_GLOBAL;
|
||||
wasmer_value_t val;
|
||||
val.tag = WASM_I32;
|
||||
val.value.I32 = 1024;
|
||||
wasmer_global_t *global = wasmer_global_new(val, false);
|
||||
global_import.value.global = global;
|
||||
|
||||
// Define a table import
|
||||
const char *import_table_name = "table";
|
||||
wasmer_byte_array import_table_name_bytes;
|
||||
import_table_name_bytes.bytes = (const uint8_t *) import_table_name;
|
||||
import_table_name_bytes.bytes_len = strlen(import_table_name);
|
||||
wasmer_import_t table_import;
|
||||
table_import.module_name = module_name_bytes;
|
||||
table_import.import_name = import_table_name_bytes;
|
||||
table_import.tag = WASM_TABLE;
|
||||
wasmer_table_t *table = NULL;
|
||||
wasmer_limits_t table_descriptor;
|
||||
table_descriptor.min = 256;
|
||||
wasmer_limit_option_t table_max;
|
||||
table_max.has_some = true;
|
||||
table_max.some = 256;
|
||||
table_descriptor.max = table_max;
|
||||
wasmer_result_t table_result = wasmer_table_new(&table, table_descriptor);
|
||||
if (table_result != WASMER_OK)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
table_import.value.table = table;
|
||||
|
||||
|
||||
// Create arbitrary arguments for our program
|
||||
|
||||
|
||||
// Read the Wasm file bytes.
|
||||
FILE *file = fopen("assets/emscripten_hello_world.wasm", "r");
|
||||
assert(file);
|
||||
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);
|
||||
|
||||
wasmer_module_t *module = NULL;
|
||||
// Compile the WebAssembly module
|
||||
wasmer_result_t compile_result = wasmer_compile(&module, bytes, len);
|
||||
printf("Compile result: %d\n", compile_result);
|
||||
|
||||
if (compile_result != WASMER_OK)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
|
||||
assert(compile_result == WASMER_OK);
|
||||
|
||||
// Set up data for Emscripten
|
||||
wasmer_emscripten_globals_t *emscripten_globals = wasmer_emscripten_get_emscripten_globals(module);
|
||||
|
||||
if (!emscripten_globals)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
assert(emscripten_globals);
|
||||
|
||||
// Create the Emscripten import object
|
||||
wasmer_import_object_t *import_object =
|
||||
wasmer_emscripten_generate_import_object(emscripten_globals);
|
||||
|
||||
// Create our imports
|
||||
wasmer_import_t imports[] = {func_import, global_import, memory_import, table_import};
|
||||
int imports_len = sizeof(imports) / sizeof(imports[0]);
|
||||
// Add our imports to the import object
|
||||
wasmer_import_object_extend(import_object, imports, imports_len);
|
||||
|
||||
// Instantiatoe the module with our import_object
|
||||
wasmer_instance_t *instance = NULL;
|
||||
wasmer_result_t instantiate_result = wasmer_module_import_instantiate(&instance, module, import_object);
|
||||
printf("Instantiate result: %d\n", instantiate_result);
|
||||
|
||||
if (instantiate_result != WASMER_OK)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
assert(instantiate_result == WASMER_OK);
|
||||
|
||||
// Set up emscripten to be called
|
||||
wasmer_result_t setup_result = wasmer_emscripten_set_up_emscripten(instance, emscripten_globals);
|
||||
|
||||
if (setup_result != WASMER_OK)
|
||||
{
|
||||
print_wasmer_error();
|
||||
}
|
||||
|
||||
|
||||
const char *emscripten_prog_name = "emscripten_test_program";
|
||||
const char *emscripten_first_arg = "--help";
|
||||
wasmer_byte_array args[] = {
|
||||
{ .bytes = (const uint8_t *) emscripten_prog_name,
|
||||
.bytes_len = strlen(emscripten_prog_name) },
|
||||
{ .bytes = (const uint8_t *) emscripten_first_arg,
|
||||
.bytes_len = strlen(emscripten_first_arg) }
|
||||
};
|
||||
int emscripten_argc = sizeof(args) / sizeof(args[0]);
|
||||
|
||||
wasmer_result_t main_result = wasmer_emscripten_call_main(instance, args, emscripten_argc);
|
||||
|
||||
printf("Main result: %d\n", main_result);
|
||||
assert(main_result == WASMER_OK);
|
||||
|
||||
|
||||
wasmer_import_object_iter_t *func_iter = wasmer_import_object_iterate_functions(import_object);
|
||||
|
||||
puts("Functions in import object:");
|
||||
while ( !wasmer_import_object_iter_at_end(func_iter) ) {
|
||||
wasmer_import_t import;
|
||||
wasmer_result_t result = wasmer_import_object_iter_next(func_iter, &import);
|
||||
assert(result == WASMER_OK);
|
||||
|
||||
print_byte_array(&import.module_name);
|
||||
putchar(' ');
|
||||
print_byte_array(&import.import_name);
|
||||
putchar('\n');
|
||||
|
||||
assert(import.tag == WASM_FUNCTION);
|
||||
assert(import.value.func);
|
||||
wasmer_import_object_imports_destroy(&import, 1);
|
||||
}
|
||||
wasmer_import_object_iter_destroy(func_iter);
|
||||
|
||||
// Use *_destroy methods to cleanup as specified in the header documentation
|
||||
wasmer_emscripten_destroy_emscripten_globals(emscripten_globals);
|
||||
wasmer_import_func_destroy(func);
|
||||
wasmer_global_destroy(global);
|
||||
wasmer_memory_destroy(memory);
|
||||
wasmer_table_destroy(table);
|
||||
wasmer_instance_destroy(instance);
|
||||
wasmer_import_object_destroy(import_object);
|
||||
wasmer_module_destroy(module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WASMER_EMSCRIPTEN_ENABLED
|
||||
#endif // WASMER_H_MACROS
|
||||
|
||||
|
||||
@ -74,6 +75,15 @@ typedef struct {
|
||||
|
||||
} wasmer_module_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} wasmer_instance_t;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *bytes;
|
||||
uint32_t bytes_len;
|
||||
} wasmer_byte_array;
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/**
|
||||
* Type used to construct an import_object_t with Emscripten imports.
|
||||
@ -94,11 +104,6 @@ typedef struct {
|
||||
|
||||
} wasmer_export_descriptor_t;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *bytes;
|
||||
uint32_t bytes_len;
|
||||
} wasmer_byte_array;
|
||||
|
||||
/**
|
||||
* Opaque pointer to `NamedExportDescriptors`.
|
||||
*/
|
||||
@ -191,10 +196,6 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
|
||||
} wasmer_instance_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} wasmer_instance_context_t;
|
||||
|
||||
typedef struct {
|
||||
@ -256,6 +257,23 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
|
||||
uint8_t *wasm_bytes,
|
||||
uint32_t wasm_bytes_len);
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/**
|
||||
* Convenience function for setting up arguments and calling the Emscripten
|
||||
* main function.
|
||||
*
|
||||
* WARNING:
|
||||
*
|
||||
* Do not call this function on untrusted code when operating without
|
||||
* additional sandboxing in place.
|
||||
* Emscripten has access to many host system calls and therefore may do very
|
||||
* bad things.
|
||||
*/
|
||||
wasmer_result_t wasmer_emscripten_call_main(wasmer_instance_t *instance,
|
||||
const wasmer_byte_array *args,
|
||||
unsigned int args_len);
|
||||
#endif
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/**
|
||||
* Destroy `wasmer_emscrpten_globals_t` created by
|
||||
@ -269,6 +287,11 @@ void wasmer_emscripten_destroy_emscripten_globals(wasmer_emscripten_globals_t *g
|
||||
* Create a `wasmer_import_object_t` with Emscripten imports, use
|
||||
* `wasmer_emscripten_get_emscripten_globals` to get a
|
||||
* `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
|
||||
*
|
||||
* WARNING:
|
||||
*1
|
||||
* This `import_object_t` contains thin-wrappers around host system calls.
|
||||
* Do not use this to execute untrusted code without additional sandboxing.
|
||||
*/
|
||||
wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
|
||||
#endif
|
||||
@ -280,6 +303,18 @@ wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscript
|
||||
wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
|
||||
#endif
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/**
|
||||
* Execute global constructors (required if the module is compiled from C++)
|
||||
* and sets up the internal environment.
|
||||
*
|
||||
* This function sets the data pointer in the same way that
|
||||
* [`wasmer_instance_context_data_set`] does.
|
||||
*/
|
||||
wasmer_result_t wasmer_emscripten_set_up_emscripten(wasmer_instance_t *instance,
|
||||
wasmer_emscripten_globals_t *globals);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Gets export descriptor kind
|
||||
*/
|
||||
|
@ -14,6 +14,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WASMER_EMSCRIPTEN_ENABLED
|
||||
#endif // WASMER_H_MACROS
|
||||
|
||||
|
||||
@ -61,6 +62,15 @@ struct wasmer_module_t {
|
||||
|
||||
};
|
||||
|
||||
struct wasmer_instance_t {
|
||||
|
||||
};
|
||||
|
||||
struct wasmer_byte_array {
|
||||
const uint8_t *bytes;
|
||||
uint32_t bytes_len;
|
||||
};
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/// Type used to construct an import_object_t with Emscripten imports.
|
||||
struct wasmer_emscripten_globals_t {
|
||||
@ -77,11 +87,6 @@ struct wasmer_export_descriptor_t {
|
||||
|
||||
};
|
||||
|
||||
struct wasmer_byte_array {
|
||||
const uint8_t *bytes;
|
||||
uint32_t bytes_len;
|
||||
};
|
||||
|
||||
/// Opaque pointer to `NamedExportDescriptors`.
|
||||
struct wasmer_export_descriptors_t {
|
||||
|
||||
@ -162,10 +167,6 @@ struct wasmer_import_object_iter_t {
|
||||
|
||||
};
|
||||
|
||||
struct wasmer_instance_t {
|
||||
|
||||
};
|
||||
|
||||
struct wasmer_instance_context_t {
|
||||
|
||||
};
|
||||
@ -223,6 +224,21 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
|
||||
uint8_t *wasm_bytes,
|
||||
uint32_t wasm_bytes_len);
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/// Convenience function for setting up arguments and calling the Emscripten
|
||||
/// main function.
|
||||
///
|
||||
/// WARNING:
|
||||
///
|
||||
/// Do not call this function on untrusted code when operating without
|
||||
/// additional sandboxing in place.
|
||||
/// Emscripten has access to many host system calls and therefore may do very
|
||||
/// bad things.
|
||||
wasmer_result_t wasmer_emscripten_call_main(wasmer_instance_t *instance,
|
||||
const wasmer_byte_array *args,
|
||||
unsigned int args_len);
|
||||
#endif
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/// Destroy `wasmer_emscrpten_globals_t` created by
|
||||
/// `wasmer_emscripten_get_emscripten_globals`.
|
||||
@ -233,6 +249,11 @@ void wasmer_emscripten_destroy_emscripten_globals(wasmer_emscripten_globals_t *g
|
||||
/// Create a `wasmer_import_object_t` with Emscripten imports, use
|
||||
/// `wasmer_emscripten_get_emscripten_globals` to get a
|
||||
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`.
|
||||
///
|
||||
/// WARNING:
|
||||
///1
|
||||
/// This `import_object_t` contains thin-wrappers around host system calls.
|
||||
/// Do not use this to execute untrusted code without additional sandboxing.
|
||||
wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
|
||||
#endif
|
||||
|
||||
@ -241,6 +262,16 @@ wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscript
|
||||
wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
|
||||
#endif
|
||||
|
||||
#if defined(WASMER_EMSCRIPTEN_ENABLED)
|
||||
/// Execute global constructors (required if the module is compiled from C++)
|
||||
/// and sets up the internal environment.
|
||||
///
|
||||
/// This function sets the data pointer in the same way that
|
||||
/// [`wasmer_instance_context_data_set`] does.
|
||||
wasmer_result_t wasmer_emscripten_set_up_emscripten(wasmer_instance_t *instance,
|
||||
wasmer_emscripten_globals_t *globals);
|
||||
#endif
|
||||
|
||||
/// Gets export descriptor kind
|
||||
wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_);
|
||||
|
||||
|
Reference in New Issue
Block a user