Embind does not seem to recognize std::function (unbound type)

1,015 views
Skip to first unread message

Vangelis Ts.

unread,
Jul 10, 2017, 8:58:08 AM7/10/17
to emscripten-discuss
Hello,

I am trying to use a simple C++ program containing using std::function with Embind. However, the latter does not seem to recognize std::function.

More specifically, here is the example I used:

Foo.cpp

 
#include <functional>
#include <emscripten/bind.h>

using namespace emscripten;

int bar(std::function<int(int)> func, int num) {
return func(num);
}

EMSCRIPTEN_BINDINGS(Foo) {
function("bar", &bar);
}


Foo.html


<!doctype html>
<html>
<script src="foo.js"></script>
<script>
console.log('Foo: ' + Module.bar);
</script>
</html>


Compilation


$ emcc --bind foo.cpp -o foo.js


The compilation succeeds with no errors or warnings.

Result



I also tried to compile and/or run the test files of Embind (see embind_test.cpp and embind.test.js), which also contain function that use std::function (e.g. emval_test_get_function_ptr (definition) / emval_test_get_function_ptr (binding)), with exactly the same command and they do work fine:

Result


Generated source code


I should also mention that I tried many different combinations, e.g. std::function with different types, as return type, as argument, as an independent function (like in the above example), as a class or struct method, but had no luck.

Any ideas would prove of great help.

Thank you very much, in advance.


― Vangelis

Alexandre Perrot

unread,
Jul 17, 2017, 3:24:49 AM7/17/17
to emscripten-discuss
Hi,

std::functions are not bound by default, you need to do that yourself.

Have a look at l.1775 of embind_test.cpp
https://github.com/kripken/emscripten/blob/master/tests/embind/embind_test.cpp#L1775

This registers an std::function as a class, with the opcall method binding the c++ () operator.

Alternatively, you could use an emscripten::val to pass a function from js.

Vangelis Ts.

unread,
Jul 17, 2017, 11:44:18 AM7/17/17
to emscripten-discuss
Thank you very much for your response, Alexandre. 🙂

Passing functions from JS to call later on from C++ is exactly what I am trying to do. I suspect that emscripten::val is the only way ―or is it also possible by using std::function?

In any case, my C++ library uses std::function internally and (ideally) I would like to avoid making changes to the code that calls the callbacks. Is there the ability to "translate" an emscripten::val to std::function, in order to transparently pass the callbacks to the rest C++ code?

Alexandre Perrot

unread,
Jul 19, 2017, 10:19:26 AM7/19/17
to emscripten-discuss
Both are possible, but I'd say val is the best option.

I did not test it, but it seems to me that since val has an operator(), it can be used as a functor, and thus be directly passed as an std::function.
Otherwise, it is easy to create a lambda that will call it.

Vangelis Ts.

unread,
Jul 23, 2017, 6:27:58 PM7/23/17
to emscripten-discuss
I managed to make everything work as expected. Your comments have been really helpful, Alexandre, thank you! 😀

Paulo Coutinho

unread,
Jan 10, 2023, 11:07:53 PM1/10/23
to emscripten-discuss
Hi,

I solved the problem, but only one error happen when i call the callback:

```
Cannot pass deleted object as a pointer of type XVoidFunctorString const*
```


The line where it happen is here:
https://github.com/xplpc/xplpc/blob/wasm-mapping/wasm/sample/src/xplpc/proxy/platform-proxy.ts#L36

```
EMSCRIPTEN_BINDINGS(xplpc_std_function)
{
    em::class_<std::function<void(const std::string &)>>("XVoidFunctorString")
        .constructor<>()
        .function("exec", &std::function<void(const std::string &)>::operator());
}
```


The binding for callback is here:
https://github.com/xplpc/xplpc/blob/wasm-mapping/wasm/lib/src/bind.cpp#L41-L81

If i remove the line `await this.sleep(3000);` it works, so can be something related from free memory in some place.

What im doing wrong?

This part is documented in emscriptem tests here:
https://github.com/emscripten-core/emscripten/blob/main/test/embind/embind_test.cpp#L1952-L1958

Thanks.
Reply all
Reply to author
Forward
0 new messages