WebAssembly / WebAssembly/binaryen
Dynamic Linking with emscripten.
Nobody has claimed this yet.
- Dominant language
- WebAssembly
- Stars
- 8.6k
- Forks
- 885
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 69
Description
Hi,
I have been trying to experiment with dynamic linking of wasm modules i.e. module 1 would export func foo, and module 2 would import foo.
I have primarily referred to https://webassembly.org/docs/dynamic-linking/ and https://github.com/emscripten-core/emscripten/wiki/Linking.
My code is,
square.c
#include <emscripten.h>
# define EXPORT __attribute__ ((visibility ("default")))
EXPORT EMSCRIPTEN_KEEPALIVE
int square(int x) {
return x * x;
}
cube.c
# define EXPORT __attribute__ ((visibility ("default")))
# define IMPORT __attribute__ ((visibility ("default")))
typedef int (**PF)(int);
IMPORT PF square();
EXPORT int cube(int x) { return (*square())(x) * x; }
The emcc commands used are,
emcc square.c -Os -s WASM=1 -s -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["_square"]' -o square.wasm
emcc cube.c -Os -s WASM=1 -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["_cube"]' -o cube.wasm
The JS to load the module is based on https://gist.github.com/kripken/59c67556dc03bb6d57052fedef1e61ab
<script>
// Check for wasm support.
if (!('WebAssembly' in window)) {
alert('you need a browser with wasm support enabled :(');
}
// Loads a WebAssembly dynamic library, returns a promise.
// imports is an optional imports object
function loadWebAssembly(filename, imports) {
// Fetch the file and compile it
return fetch(filename)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
// Create the imports for the module, including the
// standard dynamic library imports
imports = imports || {};
imports.env = imports.env || {};
imports.env.__memory_base = imports.env.__memory_base || 0;
imports.env.__table_base = imports.env.__table_base || 0;
if (!imports.env.memory) {
imports.env.memory = new WebAssembly.Memory({ initial: 256 });
}
if (!imports.env.table) {
imports.env.table = new WebAssembly.Table({ initial: 0, element: 'anyfunc' });
}
// Create the instance.
return new WebAssembly.Instance(module, imports);
});
}
loadWebAssembly('square.wasm')
.then(instance => {
var exports = instance.exports;
var square = exports._square;
var button = document.getElementById('run');
button.value = 'Call a method in the WebAssembly module';
button.addEventListener('click', function() {
var input = 21;
alert(input + ' square is ' + square(input));
}, false);
}
);
loadWebAssembly('cube.wasm')
.then(instance => {
var exports = instance.exports;
var cube = exports._cube;
var button = document.getElementById('run');
button.value = 'Call a method in the WebAssembly module';
button.addEventListener('click', function() {
var input = 21;
alert(input + ' cube is ' + cube(input));
}, false);
}
);
</script>
But i get error in cube.wasm instantiation as,
Uncaught (in promise) LinkError: WebAssembly Instantiation: Import #0 module="env" function="abort" error: function import requires a callable
If I change cube.wasm compile command to have the flag, -s ONLY_MY_CODE=1, then the exported function is not found.
Uncaught (in promise) LinkError: WebAssembly Instantiation: Import #0 module="env" function="_square" error: function import requires a callable
Can anyone help me. Where i am going wrong ?
Thanks.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with square.c, cube.c, the two emcc commands, and the loadWebAssembly script; compare them with the WebAssembly dynamic-linking and Emscripten Linking references included in the issue. Reproduce the abort and _square import errors, then verify that both modules instantiate and cube can call square.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, wasm
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100