How to create an API with QJSEngine?

I start with Qt, and one of my projects uses QJSEngine to evaluate javascript, and I want to provide the whole API for the script, with classes and global functions.

Right now, my program provides only ECMAScript default material (eval, encodeURI, parseInt, etc.), but I need to set some custom classes in the code, such as browser APIs (WebSocket class, image class, document object). For example:

var obj = new CustomClass("", 0); var ret = obj.customClassMethod("[...]!"); customFunction(ret); 

I need to determine the behavior of classes in C ++, this would not help evaluate the definition of classes and run the user code.

+2
c ++ javascript qt qt5 qjsengine
source share
3 answers

Unlike QScriptEngine , where you can add custom classes if they inherit from QObject using the Q_SCRIPT_DECLARE_QMETAOBJECT macro, QJSEngine does not directly provide this functionality.

You can still use the Qt meta-object system to provide interfaces for Javascript, but you need to instantiate the object in C ++ and add it to the Javascript context. Then its slots, methods defined with Q_INVOKABLE , and properties defined with Q_PROPERTY are made available from the Javascript runtime.

Now you can create a factory that instantiates your custom CustomClass for the given QJSEngine wrapped in Javascript objects:

 class CustomClassFactory : public QObject { Q_OBJECT public: CustomClassFactory(QJSEngine* engine) : m_engine(engine) {} Q_INVOKABLE QJSValue createInstance() { // The engine takes ownership and destroys the object if no longer required. return m_engine->newQObject(new CustomClass()); } private: QJSEngine* m_engine; } 

A factory instance must be created and added to the global Javascript runtime object:

 QJSEngine engine; QJSValue factoryObj = engine.newQObject(new CustomClassFactory()); engine.globalObject().setProperty("_customClassFactory", factoryObj); 

Now we can create objects in Javascript with:

 var obj = _customClassFactory.createInstance() 

Since we have come this far, let's add an additional constructor for the custom class to the Javascript runtime:

 QJSEngine engine; // Again, the QJSEngine will take ownership of the created object. QJSValue factoryObj = engine.newQObject(new CustomClassFactory()); engine.globalObject().setProperty("_customClassFactory", factoryObj); engine.evaluate( "function CustomClass() {" " return _customClassFactory.createInstance()" "}"); 

So now you can create a C ++ object in Javascript, as if you were using custom Javascript classes:

 var obj = new CustomClass() 

For the mentioned WebSocket API, you can wrap QtWebSocket for this purpose - this is exactly what I need when I came up with the proposed approach.

Note that for simplicity, I omitted the options for the constructor, but they can also just be added.

PS: I would add more links to the official documentation, but due to lack of reputation, this is forbidden to me.

+4
source share

If you look at the QScriptEngine documentation or do a search in the QScriptEngine examples, you can find some information on how to create C ++ classes for QScriptEngine.

Here is a good place to start: example link

QScriptEngine is very similar to QJsEngine, so this should not be a big problem for you.

Hope this helps :)

0
source share

Starting with Qt5.5, QScriptEngine deprecated, so only QJsEngine should be used in the future. https://wiki.qt.io/New_Features_in_Qt_5.5#Deprecated_Functionality

0
source share

All Articles