I was reading this article (https://www.smashingmagazine.com/2019/04/webassembly-speed-web-app/) that explained how they used zlib, among other things, to speed up their web project:
To support the zlib library, we use the flag USE_ZLIB; zlib is so common that it’s already been ported to WebAssembly, and Emscripten will include it for us in our project
I would like to use zlib in my own WASM module.
In my C code (compiled with emcc), I wrote this interfacing function:
#include <zlib.h>
int pcf_decompress_zlib(unsigned char *input, int input_length, unsigned char *output, int output_length)
{
uLongf output_length_result = output_length;
int result = uncompress(output, &output_length_result, input, input_length);
if (result != Z_OK) {
return 0;
} else {
return output_length_result;
}
}
I compiled it like so:
emcc decompress.c -O3 -s WASM=1 -s SIDE_MODULE=1 -s "EXPORTED_FUNCTIONS=['_pcf_decompress_zlib']" -s USE_ZLIB=1 -o decompress.wasm
When I did that, emcc automatically downloaded in a zlib library, so it seemed to know how to handle this.
Then in the browser, I have this class:
export class Decompressor {
wasmOnLoad(obj) {
this.instance = obj.instance;
console.log("Loaded WASM");
console.log(obj.instance);
// Don't do anything else yet
}
constructor() {
this.memory = new WebAssembly.Memory({
initial: 1
});
this.heap = new Uint8Array(this.memory.buffer);
this.imports = {
env: {
__memory_base: 0,
memory: this.memory,
abort: function(err) {
throw new Error('abort ' + err);
},
}
};
}
start() {
console.log("startWasm");
WebAssembly.instantiateStreaming(fetch('decompress/decompress.wasm'), this.imports)
.then(this.wasmOnLoad.bind(this));
}
}
And then this in my main JS code loaded from my HTML:
import { Decompressor } from "./decompress/decompress.js";
var l = new Decompressor();
l.start();
When I load the page, Firefox gives me this error:
LinkError: import object field '_uncompress' is not a Function
It appears that the wasm code being emitted doesn't include zlib, and zlib is also not built into the browser. I thought about changing SIDE_MODULE
to MAIN_MODULE
, but that resulted in dozens of undefined symbols, making the problem even worse.
There would be no point in having emcc provide a USE_ZLIB=1
option if it didn't automatically make zlib available. So what am I missing t make this work? How do I get emcc to statically include the zlib code that it already has into the wasm module I'm compiling?
Thanks.