最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Embind pass lambda function as callback parameter - Stack Overflow

programmeradmin6浏览0评论

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 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
Share Improve this question asked Apr 2, 2016 at 8:49 Iter AtorIter Ator 9,33421 gold badges89 silver badges183 bronze badges 1
  • There is a thread about this on the emscripten GitHub, looks like it is possible using embind. github./kripken/emscripten/issues/4927 – abcthomas Commented Aug 23, 2017 at 14:27
Add a ment  | 

3 Answers 3

Reset to default 5

I'm not sure if it's the only way, but to pass callbacks from Js -> C++, I've had to

  • Not use std::function, but raw function pointers
  • Use Runtime.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.
  • Not use 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"):

Moduleall('calculate', 'number', ['number'], [callbackPointer]);

and then piling 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>().)

You can use Scapix to pass parameters like std::function, std::vector, std::map, etc.

In addition to generating bindings automatically, Scapix also adds conversion layer for (arbitrarily nested) mon C++ Standard Library types.

Disclaimer: I am the author of Scapix Language Bridge.

发布评论

评论列表(0)

  1. 暂无评论