The way I did this was to create "proxy" functions that do the necessary operations. For example:
class HelloWorld
{
int x;
public:
HelloWorld() { x = 0; }
~HelloWorld() {}
void setX(int v) { x = v; }
int getX() { return x; }
// ...
};
//compile using "C" linkage to avoid name obfuscation
extern "C" {
//constructor, returns a pointer to the HelloWorld object
void *HW_constructor() {
return new HelloWorld();
}
void HW_setX(HelloWorld *hw, int x) {
hw->setX(x);
}
int HW_getX(HelloWorld *hw) {
return hw->getX();
}
void HW_destructor(HelloWorld *hw) {
delete hw;
}
};
Then in JS, you have to build a clone of your object that calls the proxy functions (annoying, I know, but I don't know of a better solution at the moment):
// get references to the exposed proxy functions
var HW_constructor = Module.cwrap('HW_constructor', 'number', []);
var HW_destructor = Module.cwrap('HW_destructor', null, ['number']);
var HW_setX = Module.cwrap('HW_setX', null, ['number', 'number']);
var HW_getX = Module.cwrap('HW_getX', 'number', ['number']);
function HelloWorld() {
this.ptr = HW_constructor();
}
HelloWorld.prototype.destroy = function () {
HW_destructor(this.ptr);
};
HelloWorld.prototype.setX = function (x) {
HW_setX(this.ptr, x);
};
HelloWorld.prototype.getX = function () {
return HW_getX(this.ptr);
};
IMPORTANT Keep in mind, in order for this to work, you need to add the following flag to your emcc command to tell it to not strip out the proxy methods as dead code (NOTE: the underscore here is intentional and important!):
emcc helloworld.cpp -o helloworld.js \
-s EXPORTED_FUNCTIONS="['_HW_constructor','_HW_destructor','_HW_setX','_HW_getX']"
EDIT: I created a gist for folks to try out the code.