I would like to create a function, which calculates something. And after it's finished, it calls the callback function.
void calculate(int param1, ..., std::function<void(void)> callback) {
//code...
callback();
}
The binding of the function is created using Embind
:
EMSCRIPTEN_BINDINGS(my_module) {
function("calculate", &calculate);
}
But if I try to call Module.calculate(0, ..., function(){/*...*/})
I get this error:
UnboundTypeError: Cannot call calculate due to unbound types: NSt3__18functionIFvvEEE
I'm not sure if it's the only way, but to pass callbacks from Js -> C++, I've had to
std::function
, but raw function pointersRuntime.addFunction
to get a C++ function pointer for a Javascript function, and pass that into the C++ world instead of trying to pass a Javascript function directly.EMBIND
, but rather the cwrap
/ccall
API.For your example, simplifying the interface slightly so only the callback is passed from JS -> C++, the C++ could look like the following:
extern "C" {
EMSCRIPTEN_KEEPALIVE
void calculate(void (*callback)()) {
callback();
}
}
The Javascript to create the callback function pointer could look like
var callbackPointer = Module.Runtime.addFunction(function() {
console.log('In the callback');
});
and to call the function, passing the pointer (as a "number"):
Module.ccall('calculate', 'number', ['number'], [callbackPointer]);
and then compiling making sure to reserve room for the function pointer:
em++ app.cpp -s RESERVED_FUNCTION_POINTERS=1 -o app.js
You can now do it like this:
void calculate(int param1, ..., emscripten::val callback) {
callback();
}
The EMSCRIPTEN_BINDINGS
is unchanged.
The callback can even take parameters, provided they are of supported/declared types (e.g. if you pass an std::vector<blah>
parameter to the callback, make sure you've used register_vector<blah>()
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With