Search code examples
webassemblyemscripten

emscripten: use globals in C


The C source of my wasm module has to use global variables because it's using code that's common to the server which does so. But I get:

Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #2 module="GOT.mem" error: module is not an object or function

when I try to use the global. Here's the code...

daft.html:

<html>
 <head>
  <meta charset=utf-8 http-equiv="Content-Language" content="en"/>
  <script src="daft.js"></script>
 </head>
</html>

daft.js:

const heap0 = new Uint8Array(mem.buffer, 0);

function squawk(cbuf,clen) {
  var s = new Uint8Array(heap0, cbuf, clen);
  let string = '';
  for (let i = 0; i < clen; i++) {
    string += String.fromCharCode(s[i]);
  }
  console.log("Squawk: "+string);
}

var imports = {
  env: {
    'memory': mem,
    'squawk': squawk,
    '__memory_base': 0,
  }
}

async function init() {
  wa = await WebAssembly.instantiateStreaming( fetch("./daft.wasm"), imports );
  wa.instance.exports.wam();
}

init();

daft.c:

#include <string.h>                    
                                       
char m[] = "Hello again. ";            
                                       
extern void squawk(const char *, int); 
                                       
void wam() {                           
  char * msg = (char *) 0;             
  strcpy(msg, "Hello from C!");        
  squawk(msg, 13);                     
}                                      
                                       
//void sorgenkind() { squawk(m, 13); }       

which I compile like so:

emcc -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s WASM=1 -s SIDE_MODULE -Os -s EXPORTED_FUNCTIONS=_wam --no-entry -o daft.wasm daft.c

As such the above code works and prints "Hello from C!" on the console. But if I uncomment sorgenkind the error occurs.

I have attempted things like:

var imports = {
  GOT: { mem: blah blah blah},
  ...

but nothing like that I tried had any effect.

It's interesting that a global integer doesn't unleash the problem. It seems that a string is the minimum. Maybe that's just cos the global int was being optimised out, as does this string, apparently, if sorgenkind is commented out.

What should I do?


Solution

  • I don't have this software installed, but it seems that you have to remove the -s SIDE_MODULE flag, and instead of -o daft.wasm use -o daft.html. According to this the extension .wasm generates only .wasm file (as when -s STANDALONE_WASM is used). But you will need more.

    The problem is that at this time the WebAssembly needs JavaScript glue code to "make it work". When you use -o draf.html you will get .html, .js and .wasm files (so care not to overwrite some of your files). In your case that is a linking error. Check this for a very simple example.

    For short you should use just this emcc daft.c -s WASM=1 -o daft.html.