Update Emscripten API layout; expose inner parts to to C API; add test

This commit is contained in:
Mark McCaskey
2019-12-16 15:45:28 -05:00
parent f1c95a81ab
commit e86b3941d0
10 changed files with 484 additions and 58 deletions

View File

@ -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( pub fn run_emscripten_instance(
_module: &Module, _module: &Module,
instance: &mut Instance, instance: &mut Instance,
@ -338,15 +393,7 @@ pub fn run_emscripten_instance(
let data_ptr = &mut data as *mut _ as *mut c_void; let data_ptr = &mut data as *mut _ as *mut c_void;
instance.context_mut().data = data_ptr; instance.context_mut().data = data_ptr;
// ATINIT set_up_emscripten(instance)?;
// (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", &[])?;
}
// println!("running 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); //let (argc, argv) = store_module_arguments(instance.context_mut(), args);
instance.call(&ep, &[Value::I32(arg as i32)])?; instance.call(&ep, &[Value::I32(arg as i32)])?;
} else { } else {
let (func_name, main_func) = match instance.dyn_func("_main") { emscripten_call_main(instance, path, &args)?;
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(),
}))
}
};
} }
// TODO atexit for emscripten // TODO atexit for emscripten

View File

@ -1,10 +1,11 @@
//! Functions and types for dealing with Emscripten imports //! Functions and types for dealing with Emscripten imports
use super::*; 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 std::ptr;
use wasmer_emscripten::EmscriptenGlobals; use wasmer_emscripten::EmscriptenGlobals;
use wasmer_runtime::Module; use wasmer_runtime::{Instance, Module};
/// Type used to construct an import_object_t with Emscripten imports. /// Type used to construct an import_object_t with Emscripten imports.
#[repr(C)] #[repr(C)]
@ -40,9 +41,88 @@ pub unsafe extern "C" fn wasmer_emscripten_destroy_emscripten_globals(
let _ = Box::from_raw(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 /// Create a `wasmer_import_object_t` with Emscripten imports, use
/// `wasmer_emscripten_get_emscripten_globals` to get a /// `wasmer_emscripten_get_emscripten_globals` to get a
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`. /// `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] #[no_mangle]
pub unsafe extern "C" fn wasmer_emscripten_generate_import_object( pub unsafe extern "C" fn wasmer_emscripten_generate_import_object(
globals: *mut wasmer_emscripten_globals_t, globals: *mut wasmer_emscripten_globals_t,

View File

@ -27,3 +27,4 @@ test-module-serialize
test-tables test-tables
test-validate test-validate
test-wasi-import-object test-wasi-import-object
test-emscripten-import-object

View File

@ -22,6 +22,11 @@ if (DEFINED WASI_TESTS)
add_executable(test-wasi-import-object test-wasi-import-object.c) add_executable(test-wasi-import-object test-wasi-import-object.c)
endif() endif()
if (DEFINED EMSCRIPTEN_TESTS)
add_executable(test-emscripten-import-object test-emscripten-import-object.c)
endif()
find_library( find_library(
WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so wasmer_runtime_c_api.dll WASMER_LIB NAMES libwasmer_runtime_c_api.dylib libwasmer_runtime_c_api.so wasmer_runtime_c_api.dll
PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/ PATHS ${CMAKE_SOURCE_DIR}/../../../target/release/
@ -74,6 +79,12 @@ if (DEFINED WASI_TESTS)
add_test(test-wasi-import-object test-wasi-import-object) add_test(test-wasi-import-object test-wasi-import-object)
endif() 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_link_libraries(test-instantiate general ${WASMER_LIB})
target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS}) target_compile_options(test-instantiate PRIVATE ${COMPILER_OPTIONS})
add_test(test-instantiate test-instantiate) add_test(test-instantiate test-instantiate)

View 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;
}

View File

@ -8,8 +8,10 @@ fn test_c_api() {
".", ".",
#[cfg(feature = "wasi")] #[cfg(feature = "wasi")]
"-DWASI_TESTS=ON", "-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("rm", project_tests_dir, vec!["-f", "CMakeCache.txt"]);
run_command("cmake", project_tests_dir, cmake_args); run_command("cmake", project_tests_dir, cmake_args);
run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]); run_command("make", project_tests_dir, vec!["-Wdev", "-Werror=dev"]);

View 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;
}

View File

@ -14,6 +14,7 @@
#endif #endif
#endif #endif
#define WASMER_EMSCRIPTEN_ENABLED
#endif // WASMER_H_MACROS #endif // WASMER_H_MACROS
@ -74,6 +75,15 @@ typedef struct {
} wasmer_module_t; } 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) #if defined(WASMER_EMSCRIPTEN_ENABLED)
/** /**
* Type used to construct an import_object_t with Emscripten imports. * Type used to construct an import_object_t with Emscripten imports.
@ -94,11 +104,6 @@ typedef struct {
} wasmer_export_descriptor_t; } wasmer_export_descriptor_t;
typedef struct {
const uint8_t *bytes;
uint32_t bytes_len;
} wasmer_byte_array;
/** /**
* Opaque pointer to `NamedExportDescriptors`. * Opaque pointer to `NamedExportDescriptors`.
*/ */
@ -191,10 +196,6 @@ typedef struct {
typedef struct { typedef struct {
} wasmer_instance_t;
typedef struct {
} wasmer_instance_context_t; } wasmer_instance_context_t;
typedef struct { typedef struct {
@ -256,6 +257,23 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
uint8_t *wasm_bytes, uint8_t *wasm_bytes,
uint32_t wasm_bytes_len); 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) #if defined(WASMER_EMSCRIPTEN_ENABLED)
/** /**
* Destroy `wasmer_emscrpten_globals_t` created by * 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 * Create a `wasmer_import_object_t` with Emscripten imports, use
* `wasmer_emscripten_get_emscripten_globals` to get a * `wasmer_emscripten_get_emscripten_globals` to get a
* `wasmer_emscripten_globals_t` from a `wasmer_module_t`. * `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); wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
#endif #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); wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
#endif #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 * Gets export descriptor kind
*/ */

View File

@ -14,6 +14,7 @@
#endif #endif
#endif #endif
#define WASMER_EMSCRIPTEN_ENABLED
#endif // WASMER_H_MACROS #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) #if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Type used to construct an import_object_t with Emscripten imports. /// Type used to construct an import_object_t with Emscripten imports.
struct wasmer_emscripten_globals_t { 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`. /// Opaque pointer to `NamedExportDescriptors`.
struct wasmer_export_descriptors_t { struct wasmer_export_descriptors_t {
@ -162,10 +167,6 @@ struct wasmer_import_object_iter_t {
}; };
struct wasmer_instance_t {
};
struct wasmer_instance_context_t { struct wasmer_instance_context_t {
}; };
@ -223,6 +224,21 @@ wasmer_result_t wasmer_compile(wasmer_module_t **module,
uint8_t *wasm_bytes, uint8_t *wasm_bytes,
uint32_t wasm_bytes_len); 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) #if defined(WASMER_EMSCRIPTEN_ENABLED)
/// Destroy `wasmer_emscrpten_globals_t` created by /// Destroy `wasmer_emscrpten_globals_t` created by
/// `wasmer_emscripten_get_emscripten_globals`. /// `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 /// Create a `wasmer_import_object_t` with Emscripten imports, use
/// `wasmer_emscripten_get_emscripten_globals` to get a /// `wasmer_emscripten_get_emscripten_globals` to get a
/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`. /// `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); wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals);
#endif #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); wasmer_emscripten_globals_t *wasmer_emscripten_get_emscripten_globals(const wasmer_module_t *module);
#endif #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 /// Gets export descriptor kind
wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_); wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_);