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(
_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