Search code examples
javascriptc++bindemscripten

binding c++ class I'm not able to find the constructor


I'm working on binding a simple c++ class into javascript. I'm doing this via Emscripten 2.0.17.

I bound hello_world.cpp

#include <iostream>

class hello {
    
public:
    
    hello() { std::cout << "Hello world!!!\n"; }
    
};

#include <emscripten/bind.h>

namespace emcc = emscripten;

EMSCRIPTEN_BINDINGS(jshello) {
    emcc::class_<hello>("hello")
        .constructor<>();   
}

using this command from terminal ./emcc_path/emcc --bind hello_world.cpp -o world.html

Then I created a main.js file like the following

var hw = require("/home/kubuntu/Desktop/c++/hello_world/hello_world.js");
var x = new hw.hello();    
x.delete();

I tried to run with node 15.14.0 using node main.js I got the following error

/home/kubuntu/Desktop/c++/hello_world/hello_world.js:117
      throw ex;
      ^

TypeError: hw.hello is not a constructor
    at Object.<anonymous> (/home/kubuntu/Desktop/c++/hello_world/main.js:3:9)
    at Module._compile (node:internal/modules/cjs/loader:1092:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
    at Module.load (node:internal/modules/cjs/loader:972:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47

Does anyone can solve say me what's worng? thanks in advance


Solution

  • Exposing a class with Emscripten

    If you want to expose a C++ class with Emscripten you need these steps, write your C++ code:

    // hello_world.cpp
    #include <iostream>
    
    class Hello {
        
    public:
        
        Hello() { 
            std::cout << "Hello world!!!\n" << std::endl;
            }
    
        void saySomething() {
            std::cout << "something" << std::endl;
        }
        
    };
    
    #include <emscripten/bind.h>
    
    using namespace emscripten;
    
    EMSCRIPTEN_BINDINGS(jshello) {
        class_<Hello>("Hello")
            .constructor<>()
            .function("saySomething", &Hello::saySomething);
    }
    

    Building with Emscripten

    build the C++ code with Emscripten, assumed that you have run the emsdk_env.sh you need to run:

    emcc --bind hello_world.cpp -o hello_world.js

    Note that the output is -o hello_world.js.

    Module in example code

    Now with the new wasm ad js files, write your main.js to load the Module:

    // main.js
    
    var Module = require("./hello_world.js");
    
    Module.onRuntimeInitialized = async function(){
        // uncommentthe code below to output the Module in the console
        // console.log('Module loaded: ', Module);
        var instance = new Module.Hello(); // this will print "Hello world!!!""
        console.log(instance); // this will pint the class as an object "Hello{}""
        instance.saySomething(); // this will print "something"
    }
    

    we wrap the code into a onRuntimeInitizialized function, in this way we are sure that our code is ready.

    Test the code!

    At this point you can test the code:

    node main.js

    The output in the console will be:

    node main.js
    Hello world!!!
    
    Hello {}
    something
    

    Example code

    You can test the code in this repository https://github.com/kalwalt/Emscripten-sketches/tree/main/hello_world_class

    Happy coding with Emscripten!