You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I want to call "host" function from "guest" using function pointer without having to include any host function in "import" object, which means that host function targets are chosen at runtime. Question: Are there any ways to do it using Wasmer? If not, do you think it is a legitimate use case and have plans for supporting it later on?
(I have talked to @MarkMcCaskey in the Wasmer slack channel about this issue and am just making it more public here for easier tracking later on.)
Additional details
Note: The Wasmer version used in the examples below is "1.0.0-alpha3".
Considering different machine model between host and guest: LP64 vs. LP32 and type check before indirect call in guest module, the only way I could come up with to dynamically call host functions is through manipulating the function pointer table of the guest module. Here is the code I have made for it.
Host source code
use wasmer::{Instance,Module,Store,Value,Type,FunctionType,Function};use wasmer_wasi::WasiState;fnhost_callback(arg1:i32,arg2:i32) -> i32{
arg1 + arg2
}fnmain() -> Result<(),Box<dyn std::error::Error>>{let wasm_bytes = std::fs::read("guest/guest.wasm")?;let store = Store::default();let module = Module::new(&store, wasm_bytes)?;letmut wasi_env = WasiState::new("hello").finalize()?;let import_object = wasi_env.import_object(&module)?;let instance = Instance::new(&module,&import_object)?;
wasi_env.set_memory(instance.exports.get_memory("memory")?.clone());letmut guest_table = instance.exports.get_table("__indirect_function_table")?;let f = Function::new_native(&store, host_callback);// Replace 1st element of the table with host_callback().
guest_table.set(1, f.into());let guest_func = instance.exports.get_function("call_callback").unwrap();// Pass the table index 1 to the guest module.let res = guest_func.call(&[Value::I32(1)])?;println!("result: {:?}", res);Ok(())}
Guest source code (==guest/guest.wasm)
int call_callback(int(*cb)(int, int)){returncb(123,456);}
One problem I encountered is that there was nothing I could do to insert a new element in the table other than replacing an existing element in the table because I couldn't resize the table. I couldn't modify maximum size of the guest table at runtime and thus failed to call Table::grow(). To work around this, I made a new Table with bigger size and overwrite the table into the Wasm instance, but it didn't work as expected emitting Trap(TableAccessOutOfBounds). Here is the code.
Host source code (Guest source code is the same as before.)
use wasmer::{Instance,Module,Store,Function,Value,TableType,Type,Table,Extern};use wasmer_wasi::WasiState;fnhost_callback(arg1:i32,arg2:i32) -> i32{
arg1 + arg2
}fnmain() -> Result<(),Box<dyn std::error::Error>>{let wasm_bytes =
std::fs::read("guest/guest.wasm").unwrap();let store = Store::default();let module = Module::new(&store, wasm_bytes)?;letmut wasi_env = WasiState::new("hello").finalize()?;let import_object = wasi_env.import_object(&module)?;letmut instance = Instance::new(&module,&import_object)?;
wasi_env.set_memory(instance.exports.get_memory("memory")?.clone());let old_table = instance.exports.get_table("__indirect_function_table")?;// Make a new table with bigger size.let new_table_ty = TableType::new(Type::FuncRef, old_table.ty().minimum,Some(old_table.ty().minimum + 10));let new_table_def_val = Function::new_native(&store, ||{});let new_table = Table::new(&store, new_table_ty, new_table_def_val.into())?;Table::copy(&new_table,0, old_table,0, old_table.ty().minimum);// Insert the new table into the guest wasm instance.
instance.exports.insert("__indirect_function_table",Extern::Table(new_table));let guest_table = instance.exports.get_table("__indirect_function_table")?;let func = Function::new_native(&store, host_callback);// Now we can grow the table with a new element.let cur_idx = guest_table.grow(1, func.into())?;let guest_func = instance.exports.get_function("call_callback")?;// Pass the new element index to the guest module.
guest_func.call(&[Value::I32(cur_idx asi32)])?;Ok(())}
Since the above code also didn't work, this time I wanted the guest wasm module to have bigger table size from the start rather than resizing it. For this, I searched for some clang compile options like --table-size-maximum=?? but there weren't such options. Besides, I searched for some APIs in Wasmer to make the table size bigger before or after the guest module is instantiated, and failed.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Summary
I want to call "host" function from "guest" using function pointer without having to include any host function in "import" object, which means that host function targets are chosen at runtime.
Question: Are there any ways to do it using Wasmer? If not, do you think it is a legitimate use case and have plans for supporting it later on?
(I have talked to @MarkMcCaskey in the Wasmer slack channel about this issue and am just making it more public here for easier tracking later on.)
Additional details
Note: The Wasmer version used in the examples below is "1.0.0-alpha3".
Considering different machine model between host and guest: LP64 vs. LP32 and type check before indirect call in guest module, the only way I could come up with to dynamically call host functions is through manipulating the function pointer table of the guest module. Here is the code I have made for it.
One problem I encountered is that there was nothing I could do to insert a new element in the table other than replacing an existing element in the table because I couldn't resize the table. I couldn't modify maximum size of the guest table at runtime and thus failed to call
Table::grow()
. To work around this, I made a new Table with bigger size and overwrite the table into the Wasm instance, but it didn't work as expected emittingTrap(TableAccessOutOfBounds)
. Here is the code.Since the above code also didn't work, this time I wanted the guest wasm module to have bigger table size from the start rather than resizing it. For this, I searched for some clang compile options like
--table-size-maximum=??
but there weren't such options. Besides, I searched for some APIs in Wasmer to make the table size bigger before or after the guest module is instantiated, and failed.Similar issue
#1302
The text was updated successfully, but these errors were encountered: