I'm trying to transpose to vue.js this simple html page add.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<input type="button" value="Add" onclick="callAdd()" />
<script>
function callAdd() {
const result = Module.ccall('Add',
'number',
['number', 'number'],
[1, 2]);
console.log(`Result: ${result}`);
}
</script>
<script src="js_plumbing.js"></script>
</body>
</html>
which calls the Add function defined in add.c :
#include <stdlib.h>
#include <emscripten.h>
// If this is an Emscripten (WebAssembly) build then...
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
#ifdef __cplusplus
extern "C" { // So that the C++ compiler does not rename our function names
#endif
EMSCRIPTEN_KEEPALIVE
int Add(int value1, int value2)
{
return (value1 + value2);
}
#ifdef __cplusplus
}
#endif
and converted to js_plumbing and js_plumbling.wasm files through the command:
emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s
ENVIRONMENT='web','worker'
In console of google chrome I get these errors:
GET http://localhost:8080/dist/js_plumbing.wasm 404 (Not Found) @ js_plumbing.js?2b2c:1653
Where in js_plumbing_js :
// Prefer streaming instantiation if available.
function instantiateAsync() {
if (!wasmBinary &&
typeof WebAssembly.instantiateStreaming === 'function'&&
!isDataURI(wasmBinaryFile) &&
typeof fetch === 'function') {
fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) { // <---------------!!!
var result = WebAssembly.instantiateStreaming(response, info);
return result.then(receiveInstantiatedSource, function(reason) {
// We expect the most common failure cause to be a bad MIME type for the binary,
// in which case falling back to ArrayBuffer instantiation should work.
err('wasm streaming compile failed: ' + reason);
err('falling back to ArrayBuffer instantiation');
instantiateArrayBuffer(receiveInstantiatedSource);
});
});
} else {
return instantiateArrayBuffer(receiveInstantiatedSource);
}
}
In Google Chrome: createWasm @ js_plumbing.js?2b2c:1680
line 1680 of js_plumbing.js:
instantiateAsync();
in Google Chrome: eval @ js_plumbing.js?2b2c:1930
line 1930 of js_plumbing.js:
<pre><font color="#4E9A06">var</font> asm = createWasm();</pre>
And many other errors related to wasm :
So... how should I modify the callAdd() method in Result.vue in order to correctly execute the Add function in js_plumbing.js and in js_plumbing.wasm files?
methods: {
callAdd() {
const result = Module.ccall('Add',
'number',
['number', 'number'],
[1, 2]);
console.log('Result: ${result}');
}
}
Updates:
1 update)
I compiled the add.c with this command:
emcc add.c -o js_plumbing.mjs -s EXTRA_EXPORTED_RUNTIME_METHODS=
['ccall','cwrap'] -s ENVIRONMENT='web' .
Then created a js_plumbing.js file :
. import wasm from './js_plumbing.mjs';
const instance = wasm({
onRuntimeInitialized() {
console.log(instance._addTwoNumbers(3,2));
}
}) .
Doing npm run dev:
Failed to compile.
./src/components/js_plumbing.mjs 3:25
Module parse failed: Unexpected token (3:25)
You may need an appropriate loader to handle this file type, currently
no loaders are configured to process this file.
See https://webpack.js.org/concepts#loaders
|
| var Module = (function() {
> var _scriptDir = import.meta.url;
|
| return (
Update 2)
I solved the 404 error by putting the wasm file into a /div subfolder within the same folder of the index.html file.
Now I’m facing this problem: “Cannot read property ‘ccall’ of undefined”
But I compiled the add.c file, creating js_plumbing.js and js_plumbing.wasm files, with this command, which exports the methods ‘ccall’ and ‘cwrap’ :
emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=[‘ccall’,‘cwrap’] -s ENVIRONMENT=‘web’,‘worker’
3° Update)
I "solved" through a sort of an hack, which I do not like at all.
This is the Result.vue file:
<template>
<div>
<p button @click="callAdd">Add!</p>
<p>Result: {{ result }}</p>
</div>
</template>
<script>
import * as js_plumbing from './js_plumbing'
import Module from './js_plumbing'
export default {
data () {
return {
result: null
}
},
methods: {
callAdd () {
const result = js_plumbing.Module.ccall('Add',
'number',
['number', 'number'],
[1, 2]);
this.result = result;
}
}
}
</script>
which is exactly the same as the one used before
The only thing I've done to make it working, is to add export to the definition of Module in js_plumbing.js :
js_plumbing.js
// Copyright 2010 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT
license and the
// University of Illinois/NCSA Open Source License. Both these
licenses can be
// found in the LICENSE file.
// The Module object: Our interface to the outside world. We import
// and export values on it. There are various ways Module can be used:
// 1. Not defined. We create it here
// 2. A function parameter, function(Module) { ..generated code.. }
// 3. pre-run appended it, var Module = {}; ..generated code..
// 4. External script tag defines var Module.
// We need to check if Module already exists (e.g. case 3 above).
// Substitution will be replaced with actual code on later stage of
the build,
// this way Closure Compiler will not mangle it (e.g. case 4. above).
// Note that if you want to run closure, and also to use Module
// after the generated code, you will need to define var Module =
{};
// before the code. Then that object will be used in the code, and you
// can continue to use Module afterwards as well.
export var Module = typeof Module !== 'undefined' ? Module : {};
But, as I said, I do not like this hack. Any suggestions on how to make the Module exportable, thus importable, without manually adding 'export' in js_plumbing.js file?
Marco