Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
197 views
in Technique[技术] by (71.8m points)

javascript - Emscripten WebAssembly: Exporting Class "Import #13 module="GOT.func" error: module is not an object or function"

I've been toying with the usage of WebAssembly in a project as an importable function module (with hope to eventually use in a React/Electron app), so I've set myself up with Emscripten and got to work using C++.

No issues implementing functions, but I have been unsuccessful with classes. I want to be able to expose and instantiate a class in JS and call the methods on it, persisting until the "task" is complete.

Below is an example from Emscripten's own website, which builds but throws an error when trying to run (likely due to my build command and JS importing process)

The error message is [TypeError: WebAssembly.instantiate(): Import #13 module="GOT.func" error: module is not an object or function].

Is what I'm trying to achieve sensible and possible?

#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"
}

question from:https://stackoverflow.com/questions/65946529/emscripten-webassembly-exporting-class-import-13-module-got-func-error-mod

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You probably don't want to use -s SIDE_MODULE. Using SIDE_MODULE enables emscripten dynamic linking (PIC) ABI which you probably don't want.

Building with --no-entry and with an output file ending in .wasm should be enough to build something that is as sand-alone as possible. However remember that emscripten's output is really designed to be run by emscripten-generated JS so you may run into complications trying to load it yourself like this.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...