jeudi 25 décembre 2014

What's the point of returning an "Undefined Value" when re-defining "print()" function for QScriptEngine?


[Background]


The default print() function of QScriptEngine prints the result to the terminal of Qt Creator IDE for debugging purpose. As a result, the output must be redirected to our texteditor if we are going to make a ECMA script interpreter ourselves.


This part of the document "Making Applications Scriptable" remains untouched since Qt 4.3.


Section "Redefining print()":



Qt Script provides a built-in print() function that can be useful for simple debugging purposes. The built-in print() function writes to standard output. You can redefine the print() function (or add your own function, e.g. debug() or log()) that redirects the text to somewhere else. The following code shows a custom print() that adds text to a QPlainTextEdit.



So here is the suggested re-definition of print():



QScriptValue QtPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}

QScriptValue calleeData = context->callee().data();
QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(calleeData.toQObject());
edit->appendPlainText(result);

return engine->undefinedValue();
}


Then, expose it to the script engine:



QScriptEngin engine;
QScriptValue fun = engine.newFunction(QtPrintFunction);
fun.setData(eng.newQObject(&edit));
engine.globalObject().setProperty("print", fun);




[Question]


I doubted the need of returning an "Undefined Value" by return engine->undefinedValue();, and it looks like the role of the argument *engine is just to return this void value.


Here is what I've done to change the function



QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine)
{
QString result;

for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
result.append(" ");
result.append(context->argument(i).toString());
}

/*
QScriptValue calleeData = context->callee().data();
QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(calleeData.toQObject());
edit->appendPlainText(result);

return engine->undefinedValue();
*/
return engine->toScriptValue(result); // ---> return the result directly
}

// ...

QScriptEngin engine;
QScriptValue fun = engine.newFunction(myPrintFunction);
fun.setData(eng.newQObject(&edit));
engine.globalObject().setProperty("print", fun);


which I think is more reasonable to me: returning an evaluated QScriptValue from script engine, and the value can later be translated to QString for output. This bypass the need of dynamic type cast, which could become messy especially for customized QObjects.


Besides, the original QtPrintFunction() carrying the pointer of GUI class for output all the time (QPlainTextEdit in the example), which seems to mess with the concept of separating GUI and the function code. Hence, I am suspecting Qt might do it just for returning an "undefined value" because she rather directly print the result in the function than return it.


But I am not sure, since my own myPrintFunction() works just fine. Any ideas?


[Example]


Input:



print(123);


Output (Qt Document QtPrintFunction()):



123
undefined


Directly print 123 to the output widget, and return an "undefined value" as QScriptValue.


Output (My version myPrintFunction()):



123


Returning 123 instead of undefined as QScriptValue, which can be translated by QScripValue::toString later to the output widget.




[Edit]:


I've found myPrintFunction didn't work well in loop, but I don't know how to explain it.


Here are different outputs with two types of print function but using the same script:


Input:



for (i = 0; i < 3; i++)
print(i);


Output (Qt Document QtPrintFunction() ):



0


1


2


undefined



Output (myPrintFunction()):



2



In fact, my myPrintFunction() only allows me to print once per script, and only the last print function will do his job. The script



print("Stack");
print("Overflow");


result will be



Overflow



for myPrintFunction(), which is not what I want.


It seems the returning of an "Undefined Value" is NECESSARY for print function. But why???





Aucun commentaire:

Enregistrer un commentaire