Emscripten WebAssembly:导出类“Import #13 module="GOT.func" 错误:模块不是对象或函数”

Posted

技术标签:

【中文标题】Emscripten WebAssembly:导出类“Import #13 module="GOT.func" 错误:模块不是对象或函数”【英文标题】:Emscripten WebAssembly: Exporting Class "Import #13 module="GOT.func" error: module is not an object or function" 【发布时间】:2021-01-28 23:10:37 【问题描述】:

我一直在玩弄在项目中将 WebAssembly 用作可导入功能模块(希望最终在 React/Electron 应用程序中使用),所以我已经使用 Emscripten 设置自己并开始使用 C++ .

实现功能没有问题,但我的课程没有成功。我希望能够在 JS 中公开和实例化一个类并调用其上的方法,一直持续到“任务”完成。

下面是一个example from Emscripten's own website,它构建但在尝试运行时抛出错误(可能是由于我的构建命令和 JS 导入过程)

错误信息是[TypeError: WebAssembly.instantiate(): Import #13 module="GOT.func" error: module is not an object or function]

我想要实现的目标是否合理且可行?

#include <stdio.h>
#include <string>
#include <iostream>
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>

using namespace emscripten;

class MyClass

public:
    MyClass(int x, std::string y)
        : x(x), y(y)
    
    

    void incrementX()
    
        ++x;
    

    int getX() const  return x; 
    void setX(int x_)  x = x_; 

    static std::string getStringFromInstance(const MyClass &instance)
    
        return instance.y;
    

private:
    int x;
    std::string y;
;

// Binding code
EMSCRIPTEN_BINDINGS(my_class_example)

    class_<MyClass>("MyClass")
        .constructor<int, std::string>()
        .function("incrementX", &MyClass::incrementX)
        .property("x", &MyClass::getX, &MyClass::setX)
        .class_function("getStringFromInstance", &MyClass::getStringFromInstance);
;
const util = require('util');
const fs = require('fs');
var source = fs.readFileSync('./dist/module.wasm');
const env = 
    memoryBase: 0,
    tableBase: 0,
    memory: new WebAssembly.Memory(
        initial: 256
    ),
    table: new WebAssembly.Table(
        initial: 0,
        element: 'anyfunc'
    ),




var typedArray = new Uint8Array(source);

WebAssembly.instantiate(typedArray, 
    env: env
).then(result => 
    console.log('MODULE: ', result.instance.exports)

).catch(e => 
    // error caught
    console.log(e);
);

  "name": "wasm-js-test",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": 
    "build-test": "rm -rf ./dist && mkdir ./dist && em++ ./src/module.cpp -O2 -s WASM=1 -s SIDE_MODULE=1 --no-entry --bind -o ./dist/module.wasm && node test.js"
  ,
  "author": "",
  "license": "ISC"


【问题讨论】:

【参考方案1】:

您可能不想使用-s SIDE_MODULE。使用 SIDE_MODULE 启用您可能不想要的 emscripten 动态链接 (PIC) ABI。

使用--no-entry 和以.wasm 结尾的输出文件构建应该足以构建尽可能独立的东西。但是请记住,emscripten 的输出实际上是为由 emscripten 生成的 JS 运行而设计的,因此您可能会在尝试像这样自己加载它时遇到麻烦。

【讨论】:

您好,感谢您的快速回复!尝试删除-s SIDE_MODULE=1,我收到错误[TypeError: WebAssembly.instantiate(): Import #13 module="wasi_snapshot_preview1" error: module is not an object or function] 现在您遇到了一个事实,即您需要实现模块所依赖的 API。您可以使用 wasm-objdump 或 wasm-dis 查看它需要哪些导入。然后,您将需要提供每个导入的实现。通常使用 emscirpten,您使用 -o &lt;something&gt;.js 构建,而 emscripten 将为您提供这些。 当我开始做教程时,我开始让 Emscripten 输出我通过 require() 导入的 JS 文件,但现在我试图导出一个类,我在文件。虽然我可以在 .wasm 文件中看到对应的字符串。我觉得我错过了什么 PROGRESS UPDATE:所以我能够使用命令 em++ ./src/testing.cpp -s --no-entry --bind -o ./dist/testing.js 构建类,并使用 onRuntimeInitialized 事件通过 JS 文件运行方法。我实际上并没有在很多地方看到这个引用。更改我想要 require() 我的 WASM 代码的方式,有什么办法可以避免这种情况?

以上是关于Emscripten WebAssembly:导出类“Import #13 module="GOT.func" 错误:模块不是对象或函数”的主要内容,如果未能解决你的问题,请参考以下文章

如何表示来自 emscripten/webassembly 调用的 void* 返回

WebAssembly:将命名空间从 C++ 库导出到 JavaScript

将 QT WebAssembly 与 Emscripten 关联

快速上手 WebAssembly 应用开发:Emscripten 使用入门

如何使用库导入编译 C 文件到 webassembly 文件(Emscripten)

如何让 JetBrains CLion 中的“cmake”工作来编译 Emscripten/WebAssembly?