I'm using the "Non-abstract virtual methods" approach (i.e. with
optional_override()) to allow my JavaScript code to subclass a C++ class and receive callback methods on it. This works okay, but currently my JavaScript code needs to maintain a Map from each JavaScript-object to its associated C++-object (as returned by
implement()) in order to call methods on the C++ superclass, and that seems like an unnecessary burden to place on the JavaScript programmer.
What I'd like to do instead is pass the C++ "this" pointer to the JavaScript callback method, so that the JavaScript callback method can access it directly without any external bookkeeping. Something like the code at the bottom of this post.
However, when I try it, I get a static_assert failure when compiling the C++ bindings:
static assertion failed due to requirement '!std::is_pointer<ISomeInterfaceClass*>::value': Implicitly binding raw pointers is illegal. Specify allow_raw_pointer<arg<?>>
117 | static_assert(!std::is_pointer<T*>::value, "Implicitly binding raw pointers is illegal. Specify allow_raw_pointer<arg<?>>");
My question is, how can I specify allow_raw_pointer<arg<0>> in a call<> call? Or is there another elegant/idiomatic way to do what I want to do, that I should be using instead?
Thanks,
Jeremy
-----
class ISomeInterfaceClass
{
public:
virtual void SomeCallbackMethod() {/* empty */}
void DoSomethingElse() {...}
};
struct ISomeInterfaceClassWrapper : public wrapper<ISomeInterfaceClass>
{
EMSCRIPTEN_WRAPPER(ISomeInterfaceClassWrapper);
virtual void SomeCallbackMethod() {call<void>("SomeCallbackMethod", this);} // Trying to pass the this-pointer causes a static_assert failure!
};
EMSCRIPTEN_BINDINGS(ISomeInterfaceClassWrapper)
{
class_<ISomeInterfaceClass>("ISomeInterfaceClass")
.allow_subclass<ISomeInterfaceClassWrapper>("ISomeInterfaceClassWrapper", constructor<IAutomationUpdateGateway*>())
.function("SomeCallbackMethod", optional_override([](ISomeInterfaceClass& self) {return self.ISomeInterfaceClass::SomeCallbackMethod();}))
}
// JavaScript code
var myJavaScriptSubclassObject =
{
SomeCallbackFunction : function(cppThis)
{
console.log("SomeCallbackFunction was called!");
cppThis.DoSomethingElse();
}
};
var mySubclassObject = Module.ISomeInterfaceClass.implement(myJavaScriptSubclassObject);
[...]