C++ std output results in wasm runtime error: null function or function signature mismatch
Closed this issue · 2 comments
I have a simple example of a wasm module:
#define export __attribute__((visibility("default")))
#include <iostream>
extern "C" export int add(int a, int b) {
std::cout << "adding " << a << " and " << b << std::endl;
return a + b;
}
I'm compiling using the following (not using emscripten):
clang++ --target=wasm32-wasi -nostartfiles -ffunction-sections -fdata-sections -fno-exceptions -Wl,--no-entry -Wl,--strip-all -Wl,--export-dynamic -Wl,--import-memory -Wl,--export-memory -fvisibility=hidden -Wl,--gc-sections --sysroot wasi-sdk-22-sysroot-dir/ -o add.wasm add.cpp
This compiles fine.
I'm then incorporating this into a simple webpage using the browser wasi shim: https://github.com/bjorn3/browser_wasi_shim. Here is my index.js for reference:
let args = [];
let fds = [
new OpenFile(new File([])), // stdin
ConsoleStdout.lineBuffered(msg => console.log(`[WASI stdout] ${msg}`)),
ConsoleStdout.lineBuffered(msg => console.warn(`[WASI stderr] ${msg}`)),
new PreopenDirectory(".", []),
];
let wasi = new WASI(args, [], fds);
const module = await WebAssembly.compileStreaming(fetch('add.wasm'));
const memory = new WebAssembly.Memory({ initial: 32 });
const env = { memory };
const instance = await WebAssembly.instantiate(module, { env, "wasi_snapshot_preview1": wasi.wasiImport });
wasi.initialize(instance)
const { add } = instance.exports
let result = add(1, 2);
console.log(`js result = ${result}`)
result = add(2, 3);
console.log(`js result = ${result}`)
This results in the following console output:
[WASI stdout] adding 1 and 2
js result = 3
[WASI stdout] adding 2 and 3
add.wasm:0x68963 Uncaught (in promise) RuntimeError: null function or function signature mismatch
at add.wasm:0x68963
at add.wasm:0x76482
at add.wasm:0x76499
at index.js:24:12
Interestingly, if I remove the std::cout
statement from my C++ source above, this works just fine; however with the std::cout
the second invocation of the add
function results in this runtime error. I've also tried different WASI shims, e.g., wasmer
but same result.
This almost certain comes down to how/when the static constrcutors and destructors are being run.
Can you try building with -mexec-model=reactor
instead of -Wl,--no-entry
, and then calling _initialize
before calling any other exports?
Thank you @sbc100! I also had to remove the -nostartfiles
flag, but that does seem to do the trick. Closing this ticket.
Learned something new today. If you have good references on the command/reactor model for further reading that would be appreciated.