pmed / v8pp

Bind C++ functions and classes into V8 JavaScript engine
http://pmed.github.io/v8pp/
Other
898 stars 120 forks source link

are std::function<R(Args...)> convertible & bindable to/from JS ? #18

Closed nouknouk closed 8 years ago

nouknouk commented 9 years ago

I would have another question (btw, don't know if "issues" is the right place for that ; tell me).

I'm looking at a convenient way to assign JS functions to C++ observables.

class MyObservable {
    private:
        std::list<std::function<bool(int)> > observerFuncs_;
    public:
        MyObservable() : observerFuncs_() {
        }
        void addObserver(std::function<bool(int)> fn) { 
            observerFuncs_.push_back(fn); 
        }
        bool triggerObservers(int value) { 
            bool allOk = true; 
            for (auto fn : observerFuncs_) {
                ok = ok && fn(value); 
            }
            return allOk;
        }
}

then:

v8pp::class_<MyObservable> JS_MyObservable(isolate);
JS_MyObservable.set("addObserver", &MyObservable::addObserver);

The compiler doesn't complain with such std::function<...> parameter, but a JS call to the function always fails:

var obj = new MyObservable();
obj.addObserver(function(myInt) { 
    console.log("myObservable callback trigerred: "+myInt); 
    return (myInt >= 42);
});

Thanks in advance.

nouknouk commented 9 years ago

Update: I had an issue in the way I was catching exception in my little V8 engine wrapper class. No I can see the exception returned by the code above, which is "Error: expected C++ wrapped object"

As a first PoC, I'm currently looking for an implementation of a custom converter struct convert<std::function<bool(int)>>, but It would be much more smarter to have something more generic to wrap all types of std::function<X(Y...)> types.

Any idea ?

pmed commented 9 years ago

The reason for the error "expected C++ wrapped object" is the std::function is a C++ class and v8pp tries to apply convert template for it, as for user wrapped class.

I'm wondering how to check in compile time if a class used with v8pp::convert has been wrapped with v8pp::class_, but I have no idea how to implement this. So such "expected..." errors for unwrapped classes appear at runtime :(

In theory, it maybe possible to create v8pp converter for std::function <-> v8::Function, like this:

template<typename R, typename ...Args>
struct convert<std::function<R(Args...)>>
{
   static std::function<R(Args...)> from_v8(..);
   static v8::Handle<v8::Function> to_v8(..);
};

Discussion here is not a problem, since there is no documentation, that is reason of issues :)

The project also has a chat at https://gitter.im/pmed/v8pp

pmed commented 8 years ago

Added lambda support in aba2c292abb3f5987f340243c6456aa8e5c5d7bf so it's now possible to wrap a lambda or std::function in a V8 value.

nouknouk commented 8 years ago

Awesome. Many thanks for that.