如何在 Webassembly 中获取 JSON 文件
How to Fetch a JSON file in Webassembly
我目前正在试验 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 模块没有'没有明显的 export/import 东西,我以前尝试加载它的方法失败了。
wasmbyfile.js:
方法一:
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
在 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 有导入语句,而你对 instantiateStreaming 的调用没有发送 importObject。
但是从 Javascript 使用 WASM 的基本方法比:只需在 WASM 中定义一个可以从 JS 调用的函数,然后从 JS 执行 "fetch",因为实例 ("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);
我目前正在试验 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 模块没有'没有明显的 export/import 东西,我以前尝试加载它的方法失败了。
wasmbyfile.js: 方法一:
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 在 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 有导入语句,而你对 instantiateStreaming 的调用没有发送 importObject。
但是从 Javascript 使用 WASM 的基本方法比:只需在 WASM 中定义一个可以从 JS 调用的函数,然后从 JS 执行 "fetch",因为实例 ("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);