fn execute()

in executor/src/wamr.rs [102:254]


    fn execute(
        &self,
        _name: String,
        arguments: FunctionArguments,
        payload: Vec<u8>,
        runtime: FunctionRuntime,
    ) -> anyhow::Result<String> {
        let wa_argv: Vec<_> = arguments.into_vec();

        let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
        let entry_name = CString::new("entrypoint").expect("CString::new failed");

        set_thread_context(Context::new(runtime))?;

        let ret = unsafe { wasm_runtime_init() };
        assert!(ret);

        // export native function
        let export_symbols: [NativeSymbol; 5] = [
            NativeSymbol {
                symbol: b"teaclave_open_input\0".as_ptr() as _,
                func_ptr: wasm_open_input as *const c_void,
                signature: b"($)i\0".as_ptr() as _,
                attachment: std::ptr::null(),
            },
            NativeSymbol {
                symbol: b"teaclave_create_output\0".as_ptr() as _,
                func_ptr: wasm_create_output as *const c_void,
                signature: b"($)i\0".as_ptr() as _,
                attachment: std::ptr::null(),
            },
            NativeSymbol {
                symbol: b"teaclave_read_file\0".as_ptr() as _,
                func_ptr: wasm_read_file as *const c_void,
                signature: b"(i*~)i\0".as_ptr() as _,
                attachment: std::ptr::null(),
            },
            NativeSymbol {
                symbol: b"teaclave_write_file\0".as_ptr() as _,
                func_ptr: wasm_write_file as *const c_void,
                signature: b"(i*~)i\0".as_ptr() as _,
                attachment: std::ptr::null(),
            },
            NativeSymbol {
                symbol: b"teaclave_close_file\0".as_ptr() as _,
                func_ptr: wasm_close_file as *const c_void,
                signature: b"(i)i\0".as_ptr() as _,
                attachment: std::ptr::null(),
            },
        ];

        let register_succeeded = unsafe {
            wasm_runtime_register_natives(
                b"env\0".as_ptr() as _,
                export_symbols.as_ptr(),
                export_symbols.len() as u32,
            )
        };
        assert!(register_succeeded);

        let module = unsafe {
            wasm_runtime_load(
                payload.as_ptr(),
                payload.len() as u32,
                error_buf.as_mut_ptr(),
                error_buf.len() as u32,
            )
        };

        assert!((module as usize) != 0);

        error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
        let module_instance = unsafe {
            wasm_runtime_instantiate(
                module,
                DEFAULT_STACK_SIZE,
                DEFAULT_HEAP_SIZE,
                error_buf.as_mut_ptr(),
                error_buf.len() as u32,
            )
        };
        assert!((module_instance as usize) != 0);

        let entry_func = unsafe {
            wasm_runtime_lookup_function(
                module_instance,
                entry_name.as_ptr() as _,
                std::ptr::null(),
            )
        };
        assert!((entry_func as usize) != 0);

        let exec_env = unsafe { wasm_runtime_create_exec_env(module_instance, DEFAULT_STACK_SIZE) };
        assert!((exec_env as usize) != 0);

        // prepare the arguments
        // for best compatibility with Teaclave, the function signature is `int entrypoint(int argc, char* argv[])`
        let cstr_argv: Vec<_> = wa_argv
            .iter()
            .map(|arg| CString::new(arg.as_str()).unwrap())
            .collect();
        let wasm_argc = 2;
        let p_argv: Vec<u32> = cstr_argv
            .iter() // do NOT into_iter()
            .map(|arg| unsafe {
                wasm_runtime_module_dup_data(
                    module_instance,
                    arg.as_ptr() as *const u8,
                    arg.to_bytes_with_nul().len() as u32,
                )
            })
            .collect();
        let func_argv = unsafe {
            wasm_runtime_module_dup_data(
                module_instance,
                p_argv.as_ptr() as *const u8,
                (p_argv.len() * 4) as u32,
            )
        };
        let wasm_argv: [u32; 2] = [p_argv.len() as u32, func_argv];

        let result =
            unsafe { wasm_runtime_call_wasm(exec_env, entry_func, wasm_argc, wasm_argv.as_ptr()) };

        // clean WAMR allocated memory
        let _ = p_argv
            .iter()
            .map(|addr| unsafe { wasm_runtime_module_free(module_instance, *addr) });
        unsafe { wasm_runtime_module_free(module_instance, func_argv) };

        let result = if result {
            let rv = wasm_argv[0] as c_int;
            log::debug!(
                "IN WAMicroRuntime::execute after `wasm_runtime_call_wasm`, {:?}",
                rv
            );
            Ok(rv.to_string())
        } else {
            let error = unsafe { CStr::from_ptr(wasm_runtime_get_exception(module_instance)) };
            log::debug!("WAMR ERROR: {:?}", error);
            Ok(error.to_str().unwrap().to_string())
        };

        unsafe { wasm_runtime_deinstantiate(module_instance) };

        unsafe { wasm_runtime_unload(module) };

        unsafe { wasm_runtime_destroy() };

        reset_thread_context()?;

        result
    }