I'm new to WebAssembly and I'm doing some experiments.
I managed to create very simple examples.
Now I would like to try using JS objects within my C++ code. Specifically,
I would like to try printing elements retrieved from windows such as location in C++ code.
This is my C++ code:
#include <string>
#include <emscripten.h>
#include <emscripten/val.h>
using namespace emscripten;
EMSCRIPTEN_KEEPALIVE
std::string decode_request(val window) {
val location = window["location"];
std::string search = location["search"].as<std::string>();
size_t pos = search.find('?');
if (pos != std::string::npos) {
return search.substr(pos + 1);
} else {
return "";
}
}
extern "C" {
EMSCRIPTEN_KEEPALIVE
const char* myFunction() {
val window = val::global("window");
std::string query = decode_request(window);
return query.c_str();
}
}
To compile, I'm using this command:
emcc -o module.js module_2.cpp -s EXPORTED_RUNTIME_METHODS="['ccall']" -lembind
And this is the result:
module_2.cpp:24:16: warning: address of stack memory associated with local variable 'query' returned [-Wreturn-stack-address]
24 | return query.c_str();
| ^~~~~
1 warning generated.
cache:INFO: generating system asset: symbol_lists/83809947191162c2d512457e4d02c5266930142b.json... (this will be cached in "/Users/myuser/Documents/Emscripten/emsdk/upstream/emscripten/cache/symbol_lists/83809947191162c2d512457e4d02c5266930142b.json" for subsequent builds)
cache:INFO: - ok
This is my HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebAssembly Example</title>
</head>
<body>
<h1>WebAssembly Example</h1>
<p id="result">Result: </p>
<button onclick="run()">Trigger</button>
<script>
function run() {
WebAssembly.instantiateStreaming(
fetch("wrapping.wasm"), {}
).then(result => {
if (!result || !result.instance || !result.instance.exports) {
console.error("Failed to instantiate WebAssembly module.");
return;
}
var sum = result.instance.exports.myFunction();
console.log("Result:", sum);
document.getElementById("result").textContent = "Result: " + sum;
}).catch(error => {
console.error("Error loading WebAssembly module:", error);
});
}
</script>
</body>
</html>
Unfortunately, I see this error in the console when I click on the button:
Error loading WebAssembly module: TypeError: WebAssembly.instantiate(): Import #0 module="env": module is not an object or function
(anonymous) @ (index):32
Promise.catch (async)
run @ (index):31
onclick @ (index):12
Any suggestions?
Normally with emscripten you have the compiler generate the code that loads the wasm module (i.e.
-o wrapping.js). You then load that.jsfile into your html and it takes care of the loading the wasm file.You can output a wasm file directly using
-o wrapping.wasmbut then you would have implement all the JS support code yourself. This is especially hard when using embind which relies a lot of generating JS support code.For more information on standalone wasm mode see https://v8.dev/blog/emscripten-standalone-wasm. In short, it not really feasible to use embind in this mode.