emscripten:在 C 中使用全局变量
emscripten: use globals in C
我的 wasm 模块的 C 源代码必须使用全局变量,因为它使用的代码对于执行此操作的服务器来说是通用的。但我得到:
Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #2 module="GOT.mem" error: module is not an object or function
当我尝试使用全局时。这是代码...
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); }
我是这样编译的:
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
因此上面的代码可以工作并打印“Hello from C!”在控制台上。但是如果我取消注释 sorgenkind
就会发生错误。
我尝试过类似的事情:
var imports = {
GOT: { mem: blah blah blah},
...
但我试过的都没有任何效果。
有趣的是,全局整数不会引发问题。似乎一个字符串是最小的。也许这只是因为全局 int 被优化掉了,这个字符串显然也是如此,如果 sorgenkind
被注释掉。
我该怎么办?
我没有安装这个软件,但似乎你必须删除 -s SIDE_MODULE
标志,而不是 -o daft.wasm
使用 -o daft.html
。根据 this,扩展名 .wasm
仅生成 .wasm
文件(与使用 -s STANDALONE_WASM
时一样)。但是你会需要更多。
问题是此时 WebAssembly 需要 JavaScript 胶水代码来“让它工作”。当您使用 -o draf.html
时,您将获得 .html
、.js
和 .wasm
文件(请注意不要覆盖您的某些文件)。在您的情况下,这是一个非常简单的示例 linking error. Check this。
简而言之,您应该只使用这个 emcc daft.c -s WASM=1 -o daft.html
。
我的 wasm 模块的 C 源代码必须使用全局变量,因为它使用的代码对于执行此操作的服务器来说是通用的。但我得到:
Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #2 module="GOT.mem" error: module is not an object or function
当我尝试使用全局时。这是代码...
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); }
我是这样编译的:
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
因此上面的代码可以工作并打印“Hello from C!”在控制台上。但是如果我取消注释 sorgenkind
就会发生错误。
我尝试过类似的事情:
var imports = {
GOT: { mem: blah blah blah},
...
但我试过的都没有任何效果。
有趣的是,全局整数不会引发问题。似乎一个字符串是最小的。也许这只是因为全局 int 被优化掉了,这个字符串显然也是如此,如果 sorgenkind
被注释掉。
我该怎么办?
我没有安装这个软件,但似乎你必须删除 -s SIDE_MODULE
标志,而不是 -o daft.wasm
使用 -o daft.html
。根据 this,扩展名 .wasm
仅生成 .wasm
文件(与使用 -s STANDALONE_WASM
时一样)。但是你会需要更多。
问题是此时 WebAssembly 需要 JavaScript 胶水代码来“让它工作”。当您使用 -o draf.html
时,您将获得 .html
、.js
和 .wasm
文件(请注意不要覆盖您的某些文件)。在您的情况下,这是一个非常简单的示例 linking error. Check this。
简而言之,您应该只使用这个 emcc daft.c -s WASM=1 -o daft.html
。