Search code examples
javascriptc++webassemblyemscriptendjinni

Unable to build C++ Class in JavaScript using Emscripten with generated Djinni Wrapper


I'm trying to generate an extremely simple WebAssembly module from a C++ class with an add function. Here is the source c++ class and the respective djinni file

// ***src/MathUtils.cpp***
#include "MathUtils.hpp"

class MathUtils_ : public MathUtils {
public:
    double add_fff64(double a, double b) override {
        return a + b;
    }
};
// ***djinni/MathUtils.djinni***
MathUtils = interface +c {
    add_fff64(a: f64, b: f64): f64;
}

Using Snapchat/Djinni's wasm interface, I've generated the following files:

// ***src/MathUtils.hpp***
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file was generated by Djinni from MathUtils.djinni

#pragma once

class MathUtils {
public:
    virtual ~MathUtils() = default;

    virtual double add_fff64(double a, double b) = 0;
};
// ***wasm/MathUtils.hpp***
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file was generated by Djinni from MathUtils.djinni

#pragma once

#include "src/MathUtils.hpp"
#include "/Users/sam/snap.djinni/support-lib/wasm/djinni_wasm.hpp"

namespace djinni_generated {

struct MathUtils : ::djinni::JsInterface<::MathUtils, MathUtils> {
    using CppType = std::shared_ptr<::MathUtils>;
    using CppOptType = std::shared_ptr<::MathUtils>;
    using JsType = em::val;
    using Boxed = MathUtils;

    static CppType toCpp(JsType j) { return _fromJs(j); }
    static JsType fromCppOpt(const CppOptType& c) { return {_toJs(c)}; }
    static JsType fromCpp(const CppType& c) {
        ::djinni::checkForNull(c.get(), "MathUtils::fromCpp");
        return fromCppOpt(c);
    }

    static em::val cppProxyMethods();

    static double add_fff64(const CppType& self, double w_a,double w_b);

};

} // namespace djinni_generated
// ***wasm/MathUtils.cpp***
// AUTOGENERATED FILE - DO NOT MODIFY!
// This file was generated by Djinni from MathUtils.djinni

#include "wasm/MathUtils.hpp"  // my header

namespace djinni_generated {

em::val MathUtils::cppProxyMethods() {
    static const em::val methods = em::val::array(std::vector<std::string> {
        "addFff64",
    });
    return methods;
}

double MathUtils::add_fff64(const CppType& self, double w_a,double w_b) {
    try {
        auto r = self->add_fff64(::djinni::F64::toCpp(w_a),
                  ::djinni::F64::toCpp(w_b));
        return ::djinni::F64::fromCpp(r);
    }
    catch(const std::exception& e) {
        return ::djinni::ExceptionHandlingTraits<::djinni::F64>::handleNativeException(e);
    }
}

EMSCRIPTEN_BINDINGS(_MathUtils) {
    em::class_<::MathUtils>("MathUtils")
        .smart_ptr<std::shared_ptr<::MathUtils>>("MathUtils")
        .function("nativeDestroy", &MathUtils::nativeDestroy)
        .function("addFff64", MathUtils::add_fff64)
        ;
}

} // namespace djinni_generated

From this, I've attempted to generate a simple native JavaScript module that allows me to call the add function in the class.

I've effectively tried run several versions of the following script with every conceivable relevant flag:

emcc wasm/MathUtils.cpp src/MathUtils.cpp /Users/sam/snap.djinni/support-lib/wasm/djinni_wasm.cpp -o out/MathUtils.js --bind

While this has indeed compiled into a JavaScript output, there is no semblance of the MathUtils class or any add_fff64 function in MathUtils.js. Indeed, when I attempt to call the add_fff64 function in a generic native html file, I get an error.

This is particularly strange to me because when debugging the generated WebAssembly file with tools such as wasm-objdump and wasm2wat, MathUtils class and addFff64 both appear.

 - 0010490: 7562 6c65 3e00 6164 6446 6666 3634 0048  uble>.addFff64.H

Online tutorials and examples make it seem so simple, but I have yet to find anyone encountering this issue. Not exactly sure what I'm doing wrong - I'm a novice with emscripten and djinni, so even any debugging advice would be great!


Solution

  • Managed to find a solution, described and highlighted in this repo here: github.com/SamKouteili/DjinniWasmDemo