[Interest] QJSEngine replacement for QScriptEngine misses newFunction
Hi, I am looking into migrating my code to QJSEngine, because of the deprecation of the QScriptEngine (QtScript). As we have used the functionality of newFunction very extensive and all related scripts are depending on this, the newFunction in QJSEngine is for us mandatory or something that creates and equivalent result. How do I currently map a native C++ class member function to the engine: QScriptValue func_sqrt = m_engine->newFunction(sqrt, liEngine); m_engine->globalObject().setProperty("sqrt", func_sqrt, QScriptValue::ReadOnly | QScriptValue::Undeletable); This is an example of a native function: QScriptValue ScriptModuleMath::sqrt(QScriptContext *context, QScriptEngine *engine, void *arg) { Q_UNUSED(engine) Q_UNUSED(arg) if (context->argumentCount()!=1) { return context->throwError( QScriptContext::SyntaxError, "sqrt(...): illegal number of arguments."); } else if (!context->argument(0).isNumber()) { return context->throwError( QScriptContext::SyntaxError, "sqrt(...): argument 1 is not a number."); } return qSqrt(context->argument(0).toNumber()); } And in this way. I can use it then in the script: value = sqrt(4); I actually don't want to map a whole QObject, because that would require a call like this: value = MyMath.sqrt(4); Is there any way to achive in QJSEngine the same result as I do within the QScriptEngine? Best Regards, Stefan ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QJSEngine replacement for QScriptEngine misses newFunction
Thanks Stephen! I found a solution, which is very similar to your approach. QJSValue myExt = m_engine->newQObject(new ScriptModuleMath()); // mount the whole class ScriptModule to the engine --> Math.sqrt(4) m_engine->globalObject().setProperty("Math", myExt); // mount only the sqrt function to the engine --> sqrt(4) m_engine->globalObject().setProperty("sqrt", myExt.property("sqrt")); the first mount allows me now to access the whole object and of course my sqrt() method. i.e. Math.sqrt(4); the second mount allows me to directly access the sqrt() method without the instance. i.e. sqrt(4); Thanks for your suggestion. Best Regards, Stefan -Original Message- From: Interest [mailto:interest-bounces+stefan.walter=lisec@qt-project.org] On Behalf Of Stephen Bryant Sent: Dienstag, 23. Februar 2016 15:12 To: interest@qt-project.org Subject: Re: [Interest] QJSEngine replacement for QScriptEngine misses newFunction Hi Stefan, On Tuesday 23 February 2016 05:34:03 Walter Stefan wrote: [...] > > And in this way. I can use it then in the script: > value = sqrt(4); > > I actually don't want to map a whole QObject, because that would > require a call like this: value = MyMath.sqrt(4); > > Is there any way to achive in QJSEngine the same result as I do within > the QScriptEngine? Is far as I know, the only way is to do the thing you don't want to: map the whole QObject. You can, however, add a JS function reference inside the engine so you can call the function without the object name. QJSEngine engine; engine.globalObject().setProperty( "MyMath", engine.newQObject( new ScriptModuleMath( ) ) ); engine.evaluate( "var sqrt=MyMath.sqrt;" ); // repeat for other functions This will now work in JS: value = sqrt(4); You'll presumably be aware that all public slots of MyMath will automatically be available as JS functions. That makes things a little easier. It seems that you also need a QObject instance, event if you only want to expose static methods. BTW: your C++ native function can use this signature: double sqrt(double); You'll get NaN if somebody calls it with a non-number. The return value is also automatically converted as there is a QJSValue constructor that takes a double. There's no direct equivalent of read-only/undeletable, unfortunately. I'm missing that too. The closest you can get is that your MyMath functions can't be altered from JS, and you can also make a read-only Q_PROPERTY. However, there is nothing stopping somebody from reassigning properties of the global object - so your 'sqrt' function and 'MyMath' object could be replaced. This may be a security concern, depending on what you're doing. Best regards, Steve ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QJSEngine replacement for QScriptEngine misses newFunction
As a workaround you can use QQmlContext::setContextObject: QQmlEngine::rootContext()->setContextObject(myMath); On Tue, Feb 23, 2016 at 2:11 PM, Stephen Bryantwrote: > Hi Stefan, > > On Tuesday 23 February 2016 05:34:03 Walter Stefan wrote: > [...] >> >> And in this way. I can use it then in the script: >> value = sqrt(4); >> >> I actually don't want to map a whole QObject, because that would require a >> call like this: value = MyMath.sqrt(4); >> >> Is there any way to achive in QJSEngine the same result as I do within the >> QScriptEngine? > > > Is far as I know, the only way is to do the thing you don't want to: map the > whole QObject. You can, however, add a JS function reference inside the > engine so you can call the function without the object name. > > QJSEngine engine; > engine.globalObject().setProperty( > "MyMath", > engine.newQObject( new ScriptModuleMath( ) ) > ); > engine.evaluate( "var sqrt=MyMath.sqrt;" ); // repeat for other functions > > This will now work in JS: value = sqrt(4); > > You'll presumably be aware that all public slots of MyMath will automatically > be available as JS functions. That makes things a little easier. > > It seems that you also need a QObject instance, event if you only want to > expose static methods. > > BTW: your C++ native function can use this signature: double sqrt(double); > You'll get NaN if somebody calls it with a non-number. The return value is > also automatically converted as there is a QJSValue constructor that takes a > double. > > > There's no direct equivalent of read-only/undeletable, unfortunately. I'm > missing that too. The closest you can get is that your MyMath functions can't > be altered from JS, and you can also make a read-only Q_PROPERTY. > > However, there is nothing stopping somebody from reassigning properties of the > global object - so your 'sqrt' function and 'MyMath' object could be replaced. > This may be a security concern, depending on what you're doing. > > > Best regards, > > Steve > ___ > Interest mailing list > Interest@qt-project.org > http://lists.qt-project.org/mailman/listinfo/interest ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QJSEngine replacement for QScriptEngine misses newFunction
Hi Stefan, On Tuesday 23 February 2016 05:34:03 Walter Stefan wrote: [...] > > And in this way. I can use it then in the script: > value = sqrt(4); > > I actually don't want to map a whole QObject, because that would require a > call like this: value = MyMath.sqrt(4); > > Is there any way to achive in QJSEngine the same result as I do within the > QScriptEngine? Is far as I know, the only way is to do the thing you don't want to: map the whole QObject. You can, however, add a JS function reference inside the engine so you can call the function without the object name. QJSEngine engine; engine.globalObject().setProperty( "MyMath", engine.newQObject( new ScriptModuleMath( ) ) ); engine.evaluate( "var sqrt=MyMath.sqrt;" ); // repeat for other functions This will now work in JS: value = sqrt(4); You'll presumably be aware that all public slots of MyMath will automatically be available as JS functions. That makes things a little easier. It seems that you also need a QObject instance, event if you only want to expose static methods. BTW: your C++ native function can use this signature: double sqrt(double); You'll get NaN if somebody calls it with a non-number. The return value is also automatically converted as there is a QJSValue constructor that takes a double. There's no direct equivalent of read-only/undeletable, unfortunately. I'm missing that too. The closest you can get is that your MyMath functions can't be altered from JS, and you can also make a read-only Q_PROPERTY. However, there is nothing stopping somebody from reassigning properties of the global object - so your 'sqrt' function and 'MyMath' object could be replaced. This may be a security concern, depending on what you're doing. Best regards, Steve ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
[Interest] QJSEngine replacement for QScriptEngine misses newFunction
Hi, I am looking into migrating my code to QJSEngine, because of the deprecation of the QScriptEngine (QtScript). As we have used the functionality of newFunction very extensive and all related scripts are depending on this, the newFunction in QJSEngine is for us mandatory or something that creates and equivalent result. How do I currently map a native C++ class member function to the engine: QScriptValue func_sqrt = m_engine->newFunction(sqrt, liEngine); m_engine->globalObject().setProperty("sqrt", func_sqrt, QScriptValue::ReadOnly | QScriptValue::Undeletable); This is an example of a native function: QScriptValue ScriptModuleMath::sqrt(QScriptContext *context, QScriptEngine *engine, void *arg) { Q_UNUSED(engine) Q_UNUSED(arg) if (context->argumentCount()!=1) { return context->throwError( QScriptContext::SyntaxError, "sqrt(...): illegal number of arguments."); } else if (!context->argument(0).isNumber()) { return context->throwError( QScriptContext::SyntaxError, "sqrt(...): argument 1 is not a number."); } return qSqrt(context->argument(0).toNumber()); } And in this way. I can use it then in the script: value = sqrt(4); I actually don't want to map a whole QObject, because that would require a call like this: value = MyMath.sqrt(4); Is there any way to achive in QJSEngine the same result as I do within the QScriptEngine? Best Regards, Stefan ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest