Open autodidaddict opened 4 years ago
I have only started writing this wrapper very recently(2 days ago to be precise), so I have to look more into the implementation source before I'll be able to create something usable. I'll try to get some examples working soon though 😄
I hope I didn't come across like I expected this stuff to be there after just a few days. I'd like to help with this if possible, though my FFI skills aren't as good as they could be.
No worries, it didn't sound like that at all. Since there isn't really much to work with in the crate, helping seems rather difficult. But I'd be happy to take some helping hands once there is a rough structure.
Very interesting, feel free to inspect my Go implementation in case it's useful, I have a few samples too (two of them use WASI): https://github.com/matiasinsaurralde/go-wasm3
Best.
Got far enough implementation-wise that it is now possible to call exported functions(though I have not tested it too much yet). Added a very small example to show how it works currently.
Took a look at the same and it definitely looks like bi-directional calls are working. It looks like there is no return value from a host function, and that the return value is the last parameter in the function list (e.g. the seconds to millis demo). So if I had a function that took 3 input parameters and had one return value, the signature for that host func (link
ed) would look like this:
unsafe extern "C" fn millis(
_rt: ffi::IM3Runtime,
p1: u64,
p2: u64,
p3: u64
retval: *mut u64,
_mem: *mut std::ffi::c_void,
) -> *const std::ffi::c_void {
// do unsafe things...
ffi::m3Err_none as _
}
?
My real goal is to be able to add a config feature flag to the wapc crate so that I can choose whether I want to compile that library using wasmtime (running on servers/server OSes) or wasm3 (running on limited/embedded devices)
No, the signature of the extern function is always the same, you would have to retrieve the arguments from the stackpointer, which is the second argument to that function.
So something like this:
unsafe extern "C" fn millis(
_rt: ffi::IM3Runtime,
sp: *mut u64,
_mem: *mut std::ffi::c_void,
) -> *const std::ffi::c_void {
let p1 = *sp;
let p2 = *sp.add(1);
let p3 = *sp.add(2);
*sp = MILLIS; // this is the return value, aka the first value on the stack will be it
ffi::m3Err_none as _ // this is the result return, whether the call was successful(m3Err_none) or not(like returning a trap for example)
}
I am thinking about how to make this nicer to use so that the consumer doesn't have to dip into this extern mess themselves, but that most likely will involve some use of macros and im not sure about how I want to do this.
I just added a small basic macro to aid in creating an extern wrapper function around a rust function that should help to avoid having to write this stuff manually. Should work in most cases I hope, haven't tested it too much yet. https://github.com/Veykril/wasm3-rs/blob/7915db91c4a7461cf827195e89124b9d91319727/examples/wasm_link.rs#L24-L27
You basically call the macro with the wrapper_function name followed by the to be wrapped functions signature. So if you have a function with the signature fn foo(bar: u64, baz: u32) -> f32
you'd call the macro with wasm3::make_func_wrapper!(foo_wrap: foo(bar: u64, baz: u32) -> f32);
@Veykril what's the easiest way to run the examples? I was able to:
python wasm_bin_builder.py ./examples/wasm/wasm_add
rustc examples/call_wasm.rs -L ./target/release/deps
But, it requires extern crate wasm3;
on top of call_wasm.rs
.
For wasm_print
I also need to specify --cfg 'feature="wasi"'
explicitly.
@vshymanskyy You can simply run an example by invoking cargo run --example call_wasm
, and cargo run --example wasm_print --features=wasi
for the wasm_print example.
@vshymanskyy You can simply run an example by invoking
cargo run --example call_wasm
, andcargo run --example wasm_print --features=wasi
for the wasm_print example.
I have some errors when running example
$ python3 wasm_bin_builder.py examples/wasm/wasm_add
Finished release [optimized] target(s) in 0.01s
$ RUST_BACKTRACE=1 cargo run --example call_wasm
error: failed to run custom build command for `wasm3-sys v0.1.2 (/media/psf/Home/opensource/wasm3-rs/wasm3-sys)`
Caused by:
process didn't exit successfully: `/media/psf/Home/opensource/wasm3-rs/target/debug/build/wasm3-sys-f63c8693949f9c0d/build-script-build` (exit status: 101)
--- stderr
thread 'main' panicked at 'Unable to generate bindings: Os { code: 2, kind: NotFound, message: "No such file or directory" }', wasm3-sys/build.rs:78:35
stack backtrace:
0: rust_begin_unwind
at /rustc/f22819bcce4abaff7d1246a56eec493418f9f4ee/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/f22819bcce4abaff7d1246a56eec493418f9f4ee/library/core/src/panicking.rs:142:14
2: core::result::unwrap_failed
at /rustc/f22819bcce4abaff7d1246a56eec493418f9f4ee/library/core/src/result.rs:1814:5
3: core::result::Result<T,E>::expect
at /rustc/f22819bcce4abaff7d1246a56eec493418f9f4ee/library/core/src/result.rs:1064:23
4: build_script_build::gen_bindings
at ./build.rs:78:18
5: build_script_build::main
at ./build.rs:127:5
6: core::ops::function::FnOnce::call_once
at /rustc/f22819bcce4abaff7d1246a56eec493418f9f4ee/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Make sure you have initialized the submodule
I'm struggling to find the right functions to call to make this work. I'd love to see a sample that utilizes the Rust bindings that:
println!()
work while under host interpretation.If there are some docs or some other source of information you can point me at, I can take a stab at this.