-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Open
Description
Coming from the C++ world, I'm struggling to understand which of the two options is correct when I'm trying to bind the pure virtual C++ class and provide the implementation on the JS side.
Suppose you have an interface like this:
// main.cpp
#include <iostream>
#include <emscripten/bind.h>
class IAction {
public:
virtual ~IAction() {
std::cout << "IAction::~IAction()" << std::endl;
}
virtual void PrintSelf() const = 0;
};
class IActionWrapper : public emscripten::wrapper<IAction> {
public:
EMSCRIPTEN_WRAPPER(IActionWrapper);
~IActionWrapper() override = default;
void PrintSelf() const override {
return call<void>("PrintSelf");
}
};
EMSCRIPTEN_BINDINGS(Factory) {
using namespace emscripten;
class_<IAction>("IAction")
.function("PrintSelf", &IAction::PrintSelf, pure_virtual())
.allow_subclass<IActionWrapper>("IActionWrapper");
}
And these are the two possible JS implementations that follow the embind docs example, one using extend
and the other one implement
:
const ActionExtend = Module.IAction.extend("IAction", {
__construct: function(name: string) {
this.__parent.__construct.call(this);
this.name = name;
},
__destruct: function() {
this.__parent.__destruct.call(this);
},
PrintSelf() {
console.log("Action:", this.name);
}
})
const ActionImplement = (name: string) => {
return Module.IAction.implement({
name: name,
PrintSelf() {
console.log("Action:", this.name);
}
});
}
const A1 = new ActionExtend("A1");
A1.PrintSelf();
console.log("Action is deleted: ", A1.isDeleted())
A1.delete();
console.log("Action is deleted: ", A1.isDeleted())
const A2 = ActionImplement("A2");
A2.PrintSelf();
console.log("Action is deleted: ", A2.isDeleted())
A2.delete();
console.log("Action is deleted: ", A2.isDeleted())
This is the log that I see in the console:
Action: A1
Action is deleted: false
IAction::~IAction()
Action is deleted: false
Action: A2
Action is deleted: false
IAction::~IAction()
Action is deleted: true
Based on the log it seems like the implement
version is the correct one. The extend
even allows the double call of .delete()
without any errors for the 2nd call, although the IAction
's destructor is only triggered once.
const A3 = new ActionExtend("A3");
A3.PrintSelf();
console.log("Action is deleted: ", A3.isDeleted())
A3.delete();
console.log("Action is deleted: ", A3.isDeleted())
A3.delete(); // Double delete - still valid, no dtor called
Is this all correct and works as expected?
Version of emscripten/emsdk:
Emscripten 4.0.15
Metadata
Metadata
Assignees
Labels
No labels