9301293
9301293

Reputation: 511

Emscripten Class Constructor Taking std::vector<T>

I was wondering if anyone could help me with binding for a C++ class, which takes an std::vector<T> as a constructor, in Emscripten. I would like something along the lines of the following:

EMSCRIPTEN_BINDINGS(my_class) {

    emscripten::class_<test_class>("test_class")
        .constructor<std::vector<float>>()
        .property("x", &test_class::get_x, &test_class::set_x)
        ;
}

I read up on this post, and implemented a proxy function to take my JS float array created by var inputArray = new Float32Array([1,2,3], to an std::vector<float>.

However, when I use the inputArray as a parameter to the class constructor I get the following warning:

5258048 - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.

I have added the DISABLE_EXCEPTION_CATCHING=2 flag to the emcc step, however, this doesn't produce any different output.

Has anyone else come up with a solution?

Upvotes: 0

Views: 1012

Answers (1)

yjjjnls
yjjjnls

Reputation: 62

The key thing is to ensure that you've defined a mapping for std::vector using register_vector so you can pass the vector your copy function has created back to JavaScript and then back into C++.

This code seems to work for me, if I understand your problem correctly:

#include <vector>

#include <emscripten.h>
#include <emscripten/bind.h>

class test_class {
    float x;

public:
    test_class(std::vector<float> arr);
    float get_x() const;
    void set_x(float val);
};

test_class::test_class(std::vector<float> arr) {
    x = 0;
    for (size_t i = 0; i < arr.size(); i++) {
        x += arr[i];
    }
    x = x / arr.size();
}

float test_class::get_x() const {
    return x;
}

void test_class::set_x(float val) {
    x = val;
}

EMSCRIPTEN_BINDINGS(my_class) {

    emscripten::register_vector<float>("VectorFloat");

    emscripten::class_<test_class>("test_class")
        .constructor<std::vector<float>>()
        .property("x", &test_class::get_x, &test_class::set_x)
        ;
}

int main() {
    EM_ASM(
        var arr = new Float32Array([1.0, 2.0, 0.5]);
        var vec = new Module.VectorFloat();
        for (var i = 0; i < arr.length; i++) {
            vec.push_back(arr[i]);
        }
        var obj = new Module.test_class(vec);
        console.log('obj.x is ' + obj.x);
    );
}

This sample code does an inefficient copy from the Float32Array to the std::vector (represented as the VectorFloat proxy object in JS), assuming you've got that part working, and concentrates on passing the vector into the constructor.

Upvotes: 1

Related Questions