Open tsangint opened 8 years ago
Those commands look ok. What is the error you see in the console?
Oh, is the error you see in the console what's in the title? "Import #0 module="env" function="abort" error: FFI is not an object"? I missed it the first time I read this.
Then the error is that the module is trying to import env.abort
. But when you instantiate the module, you don't provide any imports.
By default emcc
will generate a .js
file that will instantiate the wasm module and pass it the necessary imports automatically for you.
Instead, if you want to instantiate it yourself, you can look in the .wast
at what it expects. However, you'll need to match the ABI expectations as well, like creating the stack, libc syscall imports if you print etc. In other words, emcc
emits wasm files that are not standalone, they are designed to work with the .js
file emcc
emits for you.
In theory a wasm file could be standalone, if you don't use any imports, manage your own stack, etc. and just provide exports that are called from outside. You can try to experiment with this using the ONLY_MY_CODE
option to emcc
, but it's not much tested yet - the main focus in emscripten has been to get C and C++ programs to "just work". Doing that requires some JS, e.g., to print output, to receive input, to handle a virtual filesystem, to render to canvas, etc. But it would be good to improve support for standalone wasm files using ONLY_MY_CODE
too.
Ah I see. Is there somewhere a standalone example or do I need to defiddle the .js
file?
We don't really have a good way to generate a standalone wasm file yet from C or C++. As I said, you can try emcc
's ONLY_MY_CODE
, but it's not likely to work. This is an area that needs more work. It's just not easy to do, as C and C++ programs tend to need things we can't do in pure wasm right now, like print. But, we could define a new ABI that makes it practical, I think.
Alternatively, if you're not using C or C++, then you can use binaryen directly to generate code, and then you can generate exactly what you want in terms of imports and exports and code. The mir2wasm project is doing that for Rust, for example.
Is there actually some minimal js
file available which will work with asm.js
and .wasm
?
What do you mean "work with asm.js and wasm"?
It would be nice to have a minimal html
+js
for
And what do you mean by minimal? Something smaller than emcc
generates for you?
As explained above, we don't have a way to have a truly standalone wasm file, so something smaller than emcc
generates isn't yet possible.
However, I am working on dynamic linking of wasm now, and that might be a route to get there. On the linking
branch in this repo and binaryen-linking
branches in emscripten and emscripten-fastcomp, basic shared modules of wasm are starting to work. We could in fact create a mostly standalone way to load those, with some ABI definitions. Still things to figure out though like the C stack.
@kripken
By default emcc will generate a .js file that will instantiate the wasm module and pass it the necessary imports automatically for you.
I'm using following command to compile
emcc counter.c -s WASM=1 -s SIDE_MODULE=1 -o counter.wasm
Getting .wasm file from it, but no .js file. What did I miss?
Ok. I simply did not have to use SIDE_MODULE
flag (which is obviously opposite to 'by default').
This works fine
emcc counter.c -s WASM=1 -o counter.js
I made it work after reading some Google tutorial https://codelabs.developers.google.com/codelabs/web-assembly-intro/index.html?index=..%2F..%2Findex#3
// hello.c
#include <stdio.h>
float bezier1(float t, float p0, float p1) {
return (1 - t) * p0 + t * p1;
}
emcc hello.c -s ONLY_MY_CODE=1 -s WASM=1 -s EXPORTED_FUNCTIONS="['_bezier1']" -o hello.js
I didn't understand why I have to use underscore in function name and why I have to create a JS file. But it works.
Finally, my JS code:
const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 });
const importObj = {
env: {
abortStackOverflow: () => { throw new Error('overflow'); },
table: new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' }),
tableBase: 0,
memory: memory,
memoryBase: 1024,
STACKTOP: 0,
STACK_MAX: memory.buffer.byteLength,
}
};
fetch('hello.wasm').then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, importObj))
.then((wa) => alert(wa.instance.exports._bezier1(0.5, 10, 20)));
Overall I think there is so much overkill. As far as WebAssembly is supported in all the modern browsers I expect to just doing something like npm install c-to-wasm
and then node node_modules/.bin/c-to-wasm index.c index.wasm
. Installing all that tools, containing python etc. and doing OS specific tricks seems strange for mainstream web development toolchain.
@alexanderby
Installing all that tools, containing python etc. and doing OS specific tricks seems strange for mainstream web development toolchain.
I think so too but I suspect there will be a period of bootstrapping and then the language revolution should take off. The fact that you can use binaryen to dynamically compile subsequent wasm leads me to think there is an opportunity for radically new toolchains.
If you get an error like this (with alexanderbys code): Uncaught (in promise) LinkError: WebAssembly Instantiation: Import #1 module="env" function="__memory_base" error: global import must be a number or WebAssembly.Global object
:
https://github.com/googlecodelabs/web-assembly-introduction/issues/11
1 Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function
I use emscripten and binaryen to compiled c/c++ to wasm file.
Then there is a error in my console.
But when I replace a.out.wasm to http://blog.mikaellundin.name/assets/posts/2016-06-19-creating-a-webassembly-binary-and-running-it-in-a-browser/out.wasm(a wasm file compile by other people), It's ok. Is there anything wrong when I compile to wasm?