如何在 Vue.js 中加载 emscripten 生成的模块以使用其功能?
How load an emscripten generated module in Vue.js in order to use its functions?
正如您在此处阅读到的:https://forum.vuejs.org/t/wasm-how-to-correctly-call-a-webassembly-method-in-vue-js/83422/24 我正在尝试弄清楚如何在 Vue.js 中导入由 emscripten 生成的模块以调用其方法。
按照此处找到的指示: 我使用以下命令编译了 add.c:
emcc add.c -o js_plumbing.js -s EXPORTED_FUNCTIONS="['_Add']" -s
EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s EXPORT_ES6=1 -s
MODULARIZE=1
并以这种方式相应地修改了Result.vue:
<template>
<div>
<p button @click="callAdd">Add!</p>
<p>Result: {{ result }}</p>
</div>
</template>
<script>
import Module from './js_plumbing'
const mymod = Module();
export default {
data () {
return {
result: null
}
},
methods: {
callAdd() {
const result = mymod.cwrap('Add',
'number',
['number', 'number'],
[1, 2]);
this.result = result;
}
}
}
</script>
但是我得到了这个错误:
Failed to compile.
./src/components/js_plumbing.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token, expected ( (3:25)
1 |
2 | var Module = (function() {
> 3 | var _scriptDir = import.meta.url;
| ^
4 |
5 | return (
6 | function(Module) {
我发现导入 emscripten 生成的模块并使用其功能的唯一方法是使用一种 "hack":在 [=68= 的模块定义中手动添加 'export' 关键字], 通过编译 add.c 生成的 javascript 文件:
emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s
ENVIRONMENT='web','worker'
Result.vue :
<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>
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 : {};
但是,正如我所说,我不喜欢这种手动破解。
关于如何使模块可导出,从而可导入,而无需在 js_plumbing.js 文件中手动添加“导出”的任何建议?
1°更新)
按照此处的答案指示:How to call a webassembly method in vue.js?
我是这样编译add.c文件的:
emcc add.c -o js_plumbing.js -s MODULARIZE=1
然后修改Result.vue如下:
<template>
<div>
<p button @click="callAdd">Add!</p>
<p>Result: {{ result }}</p>
</div>
</template>
<script>
import Module from './js_plumbing'
export default {
data () {
return {
result: null
}
},
methods: {
callAdd() {
const instance = Module({
onRuntimeInitialized() {
console.log(instance._Add(1,2));
this.result = instance._Add(1,2);
}
})
}
}
}
</script>
肯定是我哪里做错了,因为当我点击“添加”时确实得到了 console.log!按钮,但输出未传输到 Result.vue 的 html 部分:
import Module from './js_plumbing';
let instance = {
ready: new Promise(resolve => {
Module({
onRuntimeInitialized () {
instance = Object.assign(this, {
ready: Promise.resolve()
});
resolve();
}
});
})
};
export default {
data () {
return {
result: null
};
},
methods: {
callAdd(a, b) {
instance.ready
.then(_ => this.result = instance._Add(a, b));
}
}
};
本书 "WebAssembly in action" 的作者 Gerard Gallant 找到了该问题的另一个出色解决方案:https://github.com/emscripten-core/emscripten/issues/10114
正如您在此处阅读到的:https://forum.vuejs.org/t/wasm-how-to-correctly-call-a-webassembly-method-in-vue-js/83422/24 我正在尝试弄清楚如何在 Vue.js 中导入由 emscripten 生成的模块以调用其方法。
按照此处找到的指示:
emcc add.c -o js_plumbing.js -s EXPORTED_FUNCTIONS="['_Add']" -s
EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s EXPORT_ES6=1 -s
MODULARIZE=1
并以这种方式相应地修改了Result.vue:
<template>
<div>
<p button @click="callAdd">Add!</p>
<p>Result: {{ result }}</p>
</div>
</template>
<script>
import Module from './js_plumbing'
const mymod = Module();
export default {
data () {
return {
result: null
}
},
methods: {
callAdd() {
const result = mymod.cwrap('Add',
'number',
['number', 'number'],
[1, 2]);
this.result = result;
}
}
}
</script>
但是我得到了这个错误:
Failed to compile.
./src/components/js_plumbing.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token, expected ( (3:25)
1 |
2 | var Module = (function() {
> 3 | var _scriptDir = import.meta.url;
| ^
4 |
5 | return (
6 | function(Module) {
我发现导入 emscripten 生成的模块并使用其功能的唯一方法是使用一种 "hack":在 [=68= 的模块定义中手动添加 'export' 关键字], 通过编译 add.c 生成的 javascript 文件:
emcc add.c -o js_plumbing.js -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap'] -s
ENVIRONMENT='web','worker'
Result.vue :
<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>
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 : {};
但是,正如我所说,我不喜欢这种手动破解。 关于如何使模块可导出,从而可导入,而无需在 js_plumbing.js 文件中手动添加“导出”的任何建议?
1°更新)
按照此处的答案指示:How to call a webassembly method in vue.js?
我是这样编译add.c文件的:
emcc add.c -o js_plumbing.js -s MODULARIZE=1
然后修改Result.vue如下:
<template>
<div>
<p button @click="callAdd">Add!</p>
<p>Result: {{ result }}</p>
</div>
</template>
<script>
import Module from './js_plumbing'
export default {
data () {
return {
result: null
}
},
methods: {
callAdd() {
const instance = Module({
onRuntimeInitialized() {
console.log(instance._Add(1,2));
this.result = instance._Add(1,2);
}
})
}
}
}
</script>
肯定是我哪里做错了,因为当我点击“添加”时确实得到了 console.log!按钮,但输出未传输到 Result.vue 的 html 部分:
import Module from './js_plumbing';
let instance = {
ready: new Promise(resolve => {
Module({
onRuntimeInitialized () {
instance = Object.assign(this, {
ready: Promise.resolve()
});
resolve();
}
});
})
};
export default {
data () {
return {
result: null
};
},
methods: {
callAdd(a, b) {
instance.ready
.then(_ => this.result = instance._Add(a, b));
}
}
};
本书 "WebAssembly in action" 的作者 Gerard Gallant 找到了该问题的另一个出色解决方案:https://github.com/emscripten-core/emscripten/issues/10114