fetch - 如何在 Webassembly 中获取 JSON 文件
问题描述
我目前正在尝试使用 Webassembly,我在这里尝试做的一件事是使用 Webassembly 从 JSON 文件中获取数据,将其编译为 .wasm 模块,并在 Javascript 中使用该模块来读取结果拿来。
我已经尝试遵循https://kripken.github.io/emscripten-site/docs/api_reference/fetch.html上的代码,但生成的 .wasm 代码让我感到困惑,因为我找不到如何正确加载它Javascript 中的 .wasm 模块。
万一我走错了路,我真的需要一些帮助。
从这个 fetch.c 文件开始,该文件应该从文件中获取 JSON 数据。
#include <stdio.h>
#include <string.h>
#include <emscripten/fetch.h>
/*////////////////////////
// This file contains the code for fetching
// -> Compiled to .wasm file with emscripten <-
*////////////////////////
void downloadSucceeded(emscripten_fetch_t *fetch) {
printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
// The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
emscripten_fetch_close(fetch); // Free data associated with the fetch.
}
void downloadFailed(emscripten_fetch_t *fetch) {
printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
emscripten_fetch_close(fetch); // Also free data on failure.
}
int main() {
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "GET");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE;
attr.onsuccess = downloadSucceeded;
attr.onerror = downloadFailed;
emscripten_fetch(&attr, "./json/bol_list1.json");
}
我编译了这个:emcc wasm/fetch.c -Os -s WASM=1 -s FETCH=1 -s SIDE_MODULE=1 -s BINARYEN_ASYNC_COMPILATION=0 -o wasm/fetch.wasm
fetch.wasm:https ://pastebin.com/cHYpgazy
所以,现在有了那个模块,我应该用 Javascript 读取它并得到结果,但这就是我被卡住的地方,因为与其他示例相反,这个 .wasm 模块没有明显的导出/导入的东西和我以前尝试加载它的方法失败了。
wasmbyfile.js:方法 1:
let obj;
loadWebAssembly('./wasm/fetch.wasm') //Testing function
.then(instance => {
obj = instance.exports._main;
console.log(obj);
});
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer())
.then(bits => WebAssembly.compile(bits))
.then(module => { return new WebAssembly.Instance(module) });
};
错误结果:wasmbyfile.js:64 Uncaught (in promise) TypeError: WebAssembly Instantiation: Imports argument must be present and must be an object at fetch.then.then.then.module (wasmbyfile.js:64)
方法二:
(async () => {
const fetchPromise = fetch('./wasm/fetch.wasm');
const { instance } = await WebAssembly.instantiateStreaming(fetchPromise);
const result = instance.exports._main;
console.log(result);
})();
错误结果:未捕获(在承诺中)类型错误:WebAssembly 实例化:导入参数必须存在并且必须是对象
所以我被困在这一点上,并不确定如何在 JS 中正确加载模块。我需要一些帮助,或者我从一开始就以错误的方式做这件事,有没有更好的方法来做这件事?
解决方案
您收到错误是因为您的 WASM 具有 import 语句,而您对instantiateStreaming的调用未发送 importObject。
但是从 Javascript 中使用 WASM 的基本方法比简单得多:只需在 WASM 中定义一个可以从 JS 调用的函数,然后从 JS 中“获取”,例如(“add.wasm”):
(module
(type $t0 (func (param i32 i32) (result i32)))
(func $add (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
get_local $p0
get_local $p1
i32.add)
(export "add" (func $add)))
然后从 Javascript 调用它:
const wasmInstanceFromFile = await WebAssembly.instantiateStreaming(await fetch('add.wasm'));
let sum = wasmInstanceFromFile.instance.exports.add(1,2);
推荐阅读
- ios - 不了解 Apple Watch 伴侣应用程序是如何安装的
- codeblocks - 用于代码块的 Fortran77 编译器(win10 64 位)?
- python - 无法从网页中抓取一条静态信息
- angularjs - AngularJS 路由是否可以用于某些 URL,而常规 GET 请求可以用于其他 URL?
- reactjs - 如何在父容器内显示模式
- java - 如何从 JTable 在新窗口中填充 JTextFields
- postgresql - postgres 和 pg-admin 的关系
- c++ - OpenCL 结构对齐错误
- java - 具有多个数字的正则表达式(前瞻)
- r - 如何解决此“'xreg' 和 'newxreg' 有不同的列数”错误?