3

Is it possible to make QObject callable from Java Script? What I mean is to register QObject derived class instance like this:

QObject* obj = new MyObject();
QJSValue js_value = js_engine.newQObject(obj);

js_engine.globalObject().setProperty("myFunction", js_value);

and then to be able to call myFunction from Java Script

myFunction()

Environment: Qt 5.0.1

Edit: Main purpose of this manipulation is to register C++ function or functor in Java Script engine and to make it available not as an object's property but as a standalone function.

MaksymB
  • 1,267
  • 10
  • 33
  • 1
    What do you mean by `make QObject callable`? Making its member functions accessible? Based on your tag list: are you trying to access one of your C++ objects from JavaScript inside QML property bindings? – axxel Feb 28 '13 at 19:53
  • possible duplicate of http://stackoverflow.com/questions/943554/how-to-get-javascript-in-a-qwebview-to-create-new-instances-of-c-based-classes – Min Lin Mar 01 '13 at 01:06
  • And Qt provides a good example: http://apidocs.meego.com/1.2/qt4/webkit-imageanalyzer.html – Min Lin Mar 01 '13 at 01:07
  • axxel, what I mean under callable is when QJSValue::isCallable() returns true. In its turn it means that the object can be called from JS. Not just one of it's methods, but the object itself. – MaksymB Mar 01 '13 at 10:30
  • Min Lin, no it's not the same. – MaksymB Mar 01 '13 at 10:34
  • @Maxym, can you show an example in C++ how do you want to call `obj` itself? – Alexander Stepaniuk Mar 02 '13 at 19:47
  • @Alexander Stepaniuk, I want to call it from Java Script, not C++. But in C++ it would look like js_value.call(..). – MaksymB Mar 03 '13 at 08:39
  • 1
    @Maxym, C++ object can't be called itself. Neither in C++ nor in JS. A method can be called. It seems to me you want to call some method of `obj` class. As axxel mentioned before. – Alexander Stepaniuk Mar 03 '13 at 12:55
  • @Alexander Stepaniuk, ok, I also didn't find how to do that. I was doubting that it's not possible because then I's sort of impossible to export single function(or functor) from C++ to Java Script only an object with methods. – MaksymB Mar 03 '13 at 20:01

3 Answers3

4

I dont think it is possible to add a function to the QJSEngine globalObject directly from C++. Although this trick works:

  1. Define a QObject based class with the Q_INVOKABLE functions you want to expose to the QJSEngine.

    class MyObject : public QObject 
    {
        Q_OBJECT
    public:
        Q_INVOKABLE int myFunction(int x) 
        {
            return x + 3;
        }
    };
    
  2. Create an instance of this object and define its parent from C++. (It is important that you define a parent for your object instance. Without a parent the QJSEngine will think it owns the object and could delete it!)

    MyObject *obj = new MyObject();
    obj->setParent(QCoreApplication::instance());
    
  3. Expose your object to the QJSEngine.

    js_engine.globalObject().setProperty("myObject", js_engine.newQObject(obj));
    
  4. Transfer your object's functions to the global object from JavaScript.

     engine.evaluate("this.myFunction = myObject.myFunction");
    
  5. Remove myObject from the JavaScript environment.

     engine.evaluate("delete myObject");
    

Done!

Jonathan
  • 331
  • 2
  • 6
2

I spent too much time trying to do the same. And now I'm 99.9% sure there is no possibility to do that with current Qt build (5.0.1).

Alexandr
  • 100
  • 1
  • 9
1

If you are using Qt5, you can maybe use :

QObject* obj = new MyObject();
js_engine.globalObject().setProperty("myFunction", js_engine.toScriptValue(&obj::myFunction));

And you need that your QObject derived class has the Q_OBJECT macro and Q_INVOKABLE on each method that must be exposed.

If you are using QML, you should preferably use QQmlContext::setContextObject :

youQmlContext.setContextObject(new MyObject());

So all Q_PROPERTY, Q_INVOKABLE and Q_SLOT members of MyObject class will be available to QML/JS engine as members of the context itself.

TheBootroo
  • 7,408
  • 2
  • 31
  • 43
  • 1
    What is &obj::myFunction? 'obj' is a pointer. Does this compile? – MaksymB Mar 28 '13 at 16:18
  • still, what do you mean under this? address of a member function? then I don't understand on which object will it be called. – MaksymB Mar 29 '13 at 09:49
  • forget about this, i thought we could register a member function from a class to the JsEngine, but only Qml Engine allows this. – TheBootroo Mar 29 '13 at 19:30