Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught WasmModule::Instantiate(): Import #0 module="env" function="abort" error: FFI is not an object #670

Open
tsangint opened this issue Aug 14, 2016 · 15 comments

Comments

@tsangint
Copy link

tsangint commented Aug 14, 2016

I use emscripten and binaryen to compiled c/c++ to wasm file.

//get wast file
emcc hello.c -s "BINARYEN='/home/vagrant/emscripten/binaryen/'" -s "BINARYEN_METHOD='native-wasm'"

//get wasm file
wasm-as a.out.wast -o a.out.wasm
var xhr = new XMLHttpRequest();
xhr.open('GET', 'a.out.wasm', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
    myWasm = Wasm.instantiateModule(xhr.response);
}
xhr.send(null);

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?

@kripken
Copy link
Member

kripken commented Aug 15, 2016

Those commands look ok. What is the error you see in the console?

@bodokaiser
Copy link

I am getting the same error.

Full code

Latest emscripten, chrome canary.

@kripken
Copy link
Member

kripken commented Nov 12, 2016

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.

@bodokaiser
Copy link

Ah I see. Is there somewhere a standalone example or do I need to defiddle the .js file?

@kripken
Copy link
Member

kripken commented Nov 12, 2016

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.

@bodokaiser
Copy link

Is there actually some minimal js file available which will work with asm.js and .wasm?

@kripken
Copy link
Member

kripken commented Nov 15, 2016

What do you mean "work with asm.js and wasm"?

@bodokaiser
Copy link

It would be nice to have a minimal html+js for

  • only asm.js
  • only wasm
  • wasm and asm as fallback

@kripken
Copy link
Member

kripken commented Nov 15, 2016

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.

@art-in
Copy link

art-in commented Jun 27, 2017

@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?

@art-in
Copy link

art-in commented Jun 28, 2017

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

@alexanderby
Copy link

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.

@justinmchase
Copy link

@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.

@KargJonas
Copy link

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:

googlecodelabs/web-assembly-introduction#11

@georginzhang
Copy link

georginzhang commented Dec 10, 2021

1 Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants