In Qt 4.8's scripting engine, "local" variables can be set by obtaining a QScriptContext
from QScriptEngine::pushContext
then setting the properties of its activation object. This can only be done within push/pop calls, since that's the only place a QScriptContext
is available and AFAICT there is no equivalent of QScriptEngine#evaluate
that takes a QScriptContext
to use as the environment:
QScriptEngine engine;
QScriptContext *local;
local = engine.pushContext();
local->activationObject().setProperty("value", 2); // set value=2
qDebug() << engine.evaluate("value").toNumber(); // outputs 2
engine.popContext();
Is there some way to maintain an environment to use with evaluations outside of the push/pop calls? For example, I've tried creating a QScriptValue
to use as the activation object and then setting it:
QScriptEngine engine;
QScriptContext *local;
// Use ao as activation object, set variables here, prior to pushContext.
QScriptValue ao;
ao.setProperty("value", 1);
// Test with ao:
local = engine.pushContext();
local->setActivationObject(ao);
qDebug() << engine.evaluate("value").toNumber();
engine.popContext();
But that doesn't work. It outputs nan
instead of 1
, as value
is undefined. For some reason setActivationObject
didn't change the value.
My general goal is:
pushContext
and popContext
calls, without having to re-set all the variables in that environment every time.So:
ao
improperly? For example, there is an undocumented QScriptEngine#newActivationObject()
that yields an "unimplemented" error when used, perhaps this is a hint?How can I set up a local context but basically not have to re-configure it every time I push a context (since it's essentially lost for good every time I pop the context).
You could use global object. It will share property value accross all evaluations:
#include <QCoreApplication>
#include <QDebug>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptContext>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScriptEngine engine;
engine.globalObject().setProperty("value", 2);
engine.globalObject().setProperty("value2", 3);
qDebug() << engine.evaluate("value").toNumber(); // outputs 2
qDebug() << engine.evaluate("value2").toNumber(); // outputs 3
return a.exec();
}
Or if you do not want global scope :
#include <QCoreApplication>
#include <QDebug>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptContext>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScriptEngine engine;
QScriptContext *context;
QScriptValue scope = engine.newObject();
scope.setProperty("value", 1);
scope.setProperty("value2", 2);
context = engine.pushContext();
context->pushScope(scope);
qDebug() << engine.evaluate("value").toNumber(); // outputs 1
qDebug() << engine.evaluate("value2").toNumber(); // outputs 2
engine.popContext();
return a.exec();
}