Setting QScriptValue-local values prior to evaluating

泄露秘密 提交于 2019-12-13 07:31:15

问题


Is it possible, in Qt 4.8, from the C++ side, to set QScriptValue-local values in a QScriptEngine?

For example, let's say I have:

QScriptEngine engine;
engine.globalObject().setProperty("glob", 1000);

// ???: Set loc to, say, 42.
QScriptValue expr1 = engine.evaluate("glob + loc");
qDebug() << expr1.toNumber();

// ???: Set loc to, say, 99.
QScriptValue expr2 = engine.evaluate("glob + loc");
qDebug() << expr2.toNumber();

And I'd like the output of that to be:

1042
1099

The obvious solution to the contrived example above is to just make "loc" global and set + reset it accordingly, but for reasons that distract from this question that's not what I'm looking for. I'd like:

  • "loc" to be local to each QScriptValue
  • To not artificially modify the script strings by e.g. prepending QString().sprintf("loc = %d;", 42) or whatever to the scripts.
  • To only use a single QScriptEngine.

The only thing I could really think of to try was:

QScriptValue expr1 = engine.evaluate("glob + loc");
expr1.setProperty("loc", 42);
qDebug() << expr1.toNumber();

But it seems the value is already fully evaluated by evaluate() and so setProperty() has no effect (no surprise there).

I also had a peek at QScriptProgram hoping it provided a program-local environment but alas.

I am looking at the docs, and will continue to look at them after I post this, but this is the first time I'm using QScriptEngine and I have to admit my brain is turning to mush, so I apologize if it's right there and totally obvious. I will accept RTFM as a valid answer.


回答1:


I figured it out, at least I think this is the best way. The key is QScriptEngine#pushContext() and #popContext():

QScriptEngine engine;
engine.globalObject().setProperty("glob", 1000);

QScriptContext *local;

local = engine.pushContext();
local->activationObject().setProperty("loc", 42);    
QScriptValue expr1 = engine.evaluate("glob + loc");
engine.popContext();

qDebug() << expr1.toNumber();

local = engine.pushContext();
local->activationObject().setProperty("loc", 99);    
QScriptValue expr2 = engine.evaluate("glob + loc");
engine.popContext();

qDebug() << expr2.toNumber();

And as long as a given QScriptContext is active on the stack, all QScriptValue evaluations will use it. Pre-existing variables of the same name will be overridden by subsequent contexts.

The caveat I guess is you have to make push → all evaluations → pop atomic, rather than individual evaluations, if you're going for multiple threads and one engine. I wish there were a way to pass a context to evaluate().



来源:https://stackoverflow.com/questions/39089709/setting-qscriptvalue-local-values-prior-to-evaluating

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!