Hey! I am trying to experiment with strings, but whenever I use the code I get a Failed to link module
error.
The code that I am using is:
#[no_mangle] pub extern "C" fn __modlib_return_string(ptr: *const u8, len: usize) -> *mut c_char { let string: String = String::from("Returning a string"); let cstr = CString::new(string).unwrap(); cstr.into_raw() }
Could anyone explain what am I doing wrong?
Is this extern "C"
function host code that's called from wasm code?
@Dan Gohman this function is compiled to wasm code and called externally from the host using wasmtime.
It's probably also worth mentioning that the error is Link error: wasi_snapshot_preview1/fd_write
I was going to guess that the error was because you're passing a pointer argument. This will need to be translated from a wasm pointer, which is 32-bit and relative to the wasm linear memory, to a host pointer, which I assume is 64-bit for you.
But I don't know what would cause an fd_write
link error. Can you show the code that calls fd_write
?
@Dan Gohman I kind of changed the example now. Nevertheless I am still getting the same error.
The module code (it basically tries to call a function from a host which loads another module). It also had to be wrapped in unsafe as without it the compiler spits out errors.
#[link(wasm_import_module = "env")] extern "C" { pub fn load(name: i32) -> i32; } #[no_mangle] pub extern "C" fn __modlib_memory() { unsafe { load(0); } }
And the load function in the host is:
pub fn load(name: i32) -> i32 { let store = Store::default(); let mod_name = format!("{}.{}", name, "wasm"); let module = Module::from_file(&store, mod_name).expect("Cannot load a module"); let instance = Instance::new(&module, &[]).expect("Cannot instantiate a module"); instances.with(|mut i| { let new_instance = ModuleInstance::new(name, instance); (*i.borrow_mut()).lock().unwrap().push(new_instance); }); // Success. return 0; }
It's a bit of a hacky code, but I suppose the error is in the modules themselves rather than in main, but of course I might be wrong.
This code calls another module, but that module is super simple without any returns and with one line of println!("OK")
I also saw this issue. Not sure if it's relevant in this case.
Oh and instances is just a:
thread_local!(static instances: Mutex<Vec<ModuleInstance>> = Mutex::new(Vec::new()));
@daubaris it looks like you're compiling for the wasm32-wasi target which requires wasi imports to be satisfied. For that you'll need to pull in the wasmtime-wasi
crate and iterate over the module exports to hook them up to wasi functions. If you want to generate a wasm module that doesn't have wasi imports you'll want to use the wasm32-unknown-unknown target. The fd_write
intrinsic here is most likely showing up because of panics, which trigger writes to stderr
@Alex Crichton Oooh, okay. By the way, about hooking up the exports, I assume you are talking about this repository. I am a bit puzzled on how this "hooking up" is done, any hints?
@daubaris oh it sort of depends, are you using the wasmtime
crate or the C API?
I am using wasmtime
crate.
Ah the hooking up happens in Instance::new
w
which has docs about what the imports argument there is
and for wasi you'd be using the wasmtime_wasi
crate
and namely the get_export
method
Hmmm, in the previously mentioned example, I already had the Instance::new
, but the problem is that load
is being called in the module itself
I think I get the idea. I'll try it out and report how it goes :+1: thanks for the help!
Last updated: Dec 23 2024 at 12:05 UTC