首页 > 解决方案 > 如何在 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 中正确加载模块。我需要一些帮助,或者我从一开始就以错误的方式做这件事,有没有更好的方法来做这件事?

标签: fetchemscriptenwebassembly

解决方案


您收到错误是因为您的 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);

推荐阅读