Hi Warren,

embind and emval don't currently support this functionality.  That doesn't
mean it's impossible, just that we haven't thought through how it work.
There are two main challenges.  Let's discuss them and see what we can do
here.

Your example of passing a lambda as an argument to to
emscripten::val::call() is great because it looks nice and simple but it
hides its unclear lifetime semantics.  That is, a C++ lambda is just sugar
for a class with a call operator.  In your example, that class is allocated
on the stack and passed by either value or rvalue reference to the call<>
function.  Since the lambda's type has never been registered with embind,
it doesn't know how to convert it into a JavaScript object.

Even if embind did know how to convert the lambda into a JavaScript object,
that JavaScript would have a pointer to a C++ heap object, which it would
then need to deallocate at some point.  How and when would it deallocate
it?  JavaScript just assumes everything's garbage collected, so it would
never notify Emscripten that it needs to free some heap memory.  Thus,
every use of this API would leak memory.

What we've done here at IMVU is have the C++ bind an interface with
callback methods on it, and then have a JavaScript implementation of that
interface that sets up the callbacks.  Something like:

struct Callbacks {
    void invoke() {
        callback();
    }

    std::function<void()> callback;
};

class_<Callbacks>("Callbacks")
    .function("invoke", &Callbacks::invoke);
    ;

Then you can have a bit of JavaScript that, when given a Callbacks object,
will do something like:

function registerCallback(cb) {
    object.on('connect', function() {
        cb.invoke();
        // when do you deallocate the callback object? that's up to your
application
    });
}

Is there a nicer approach?  Perhaps!

Maybe we could do something where we can generate JS function objects
associated with integer handles and then C++ could map each integer handle
back to the appropriate std::function...

Do you have any ideas?

On Sat, Jun 28, 2014 at 4:03 PM, Warren Seine <[email protected]> wrote:

> I'm using embind to wrap a JS library in C++. The library uses callbacks
> such as:
>>
>> object.on('connect', function() {
>>   console.log('connected');
>> });
>
> How can I use a C++ function as callback?
>
> Ideally, I'd like to do something like:
>
>> val object = val::global("object");
>> object.call<void>("on", std::string("connect"), []() {
>>   std::cout << "connected" << std::endl;
>> });
>
> which, unfortunately, throws "Uncaught BindingError: parameter 2 has
> unknown type" with a mangled lambda type name.
>
> Chad recently posted something related to C++ callbacks
> <http://chadaustin.me/2014/06/emscripten-callbacks-and-c11-lambdas/> but
> doesn't talk about this specific issue. If that's unsupported, what would
> embind need to support C++ callbacks?
>
> Also, what's the workaround?
>
>  --
> You received this message because you are subscribed to the Google Groups
> "emscripten-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Chad Austin
Technical Director, IMVU
http://engineering.imvu.com <http://www.imvu.com/members/Chad/>
http://chadaustin.me

-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to