QScriptEngine类提供用于解释的Qt Script代码的环境。
包含:QScriptEngine
继承关系:QObject的子类
例一:
QScriptEngine myEngine;
QScriptValue three = myEngine.evaluate("1 + 2");
evaluate()返回一个QScriptValue保存的解释结果。该QScriptValue类提供函数计算结果并转换为不同的C++类型(例如QScriptValue:: toString()和QScriptValue:: toNumber())。
例二:
下面的代码片段显示了一个脚本函数被定义,然后从C++中调用使用QScriptValue::()的调用的例子:
QScriptValue fun = myEngine.evaluate("(function(a, b) { return a + b; })");
QScriptValueList args;
args << 1 << 2;
QScriptValue threeAgain = fun.call(QScriptValue(), args);
如可以从上面的代码段中可以看出,一个脚本被以字符串的形式提供给解释引擎。加载脚本的一种常见方法是通过读取一个文件的内容,并通过它来evaluate(),如下代码:
QString fileName = "helloworld.qs";
QFile scriptFile(fileName);
if (!scriptFile.open(QIODevice::ReadOnly))
// handle error
QTextStream stream(&scriptFile);
QString contents = stream.readAll();
scriptFile.close();
myEngine.evaluate(contents, fileName);
上面我们通过文件名作为第二个参数来evaluate()。这并不影响解释的方式,第二个参数是用来识别脚本用于调试目的的general-purpose字符串(例如,我们的文件名现在将要通过uncaughtExceptionBacktrace() involving到脚本)。
引擎配置
globalObject()函数返回与脚本引擎相关联的全局对象。全局对象的属性可从任何脚本代码访问(也就是说,它们是全局变量)。通常情况下,解释脚本之前,你会希望通过添加一个或多个属性的全局对象来配置脚本引擎:
myEngine.globalObject().setProperty("myNumber", 123);
...
QScriptValue myNumberPlusOne = myEngine.evaluate("myNumber + 1");
添加自定义属性的脚本环境或提供脚本API是脚本相对于应用程序定制的标准方法之一。通常这些自定义属性有由newQObject()或newobject()函数,或者通过newFunction(创建构造函数)创建的对象。
脚本异常
evaluate()可以抛出一个脚本异常(如由于语法错误);在这种情况下,返回值是一个被抛出(通常是一个错误的对象)的值。您可以检查是否解释器通过调用hasUncaughtException()导致了异常。在这种情况下,你可以调用的错误对象的toString()来获取错误消息。对于目前未捕获的异常,也可通过uncaughtException()。调用clearExceptions()将导致任何未捕获的异常被清除。
QScriptValue result = myEngine.evaluate(...);
if (myEngine.hasUncaughtException()) {
int line = myEngine.uncaughtExceptionLineNumber();
qDebug() << "uncaught exception at line" << line << ":" << result.toString();
}
checkSyntax()函数可以被用来确定是否代码已经有效地传递到evaluate()。
脚本对象的创建
使用newobject()来创建一个标准的Qt Script对象;这是相当于C++的new Object()。您可以使用该对象的特定功能,在QScriptValue操纵脚本对象(例如QScriptValue::的setProperty())。同样,使用newArray()来创建一个Qt脚本数组对象。使用newDate()来创建一个日期对象,newRegExp()来创建一个RegExp对象等都是被允许的。
QObject的整合
使用newQObject()来包装一个QObject的(或子类)的指针。newQObject()返回一个代理脚本对象、特性、子类、信号或QObject的槽,它可作为代理对象的属性。不需要任何绑定代码,因为它是使用Qt元对象系统动态地进行管理。
QPushButton button;
QScriptValue scriptButton = myEngine.newQObject(&button);
myEngine.globalObject().setProperty("button", scriptButton);
myEngine.evaluate("button.checkable = true");
qDebug() << scriptButton.property("checkable").toBoolean();
scriptButton.property("show").call(); //调用show()槽
使用qScriptConnect()来一个将一个QT的信号连接到一个脚本函数;这是与Qt脚本的QObject::connect()等效的。当一个脚本函数响应一个C++的信号调用,它可能会导致脚本异常;您可以连接到signalHandlerException()信号捕捉这样的异常。
使用newQMetaObject()来封装一个QMetaObject;这给你一个基于QObject的类的"script representation"。 newQMetaObject()返回一个代理脚本对象;可作为代理对象的属性的类的枚举值。您还可以指定用于构造类的对象(例如,当构造函数是从一个脚本调用)的函数。对于具有“标准”的Qt类的构造函数,Qt的脚本可以为你提供一个默认的构造函数的脚本。详参scriptValueFromQMetaObject()。
请参阅QtScript文档上的QObject集成的详细信息。
导入扩展
使用importExtension()来导入基于插件的扩展到引擎。调用availableExtensions()来获取一个list内含所有可用的扩展。或调用importedExtensions()来获得一个list内含那些已导入扩展。
调用pushContext()打开一个新的变量域,popContext()来关闭当前作用域。如果含临时变量定义(例如var foo = 123;) 要安全的释放时,意味着解释已经完成。 【最后一句拿不准,原文为and popContext() to close the current scope. This is useful if you are implementing an extension that evaluates script code containing temporary variable definitions (e.g. var foo = 123;) that are safe to discard when evaluation has completed.】
原生功能
使用newFunction()来封装原生(C++)函数,包括自己构造自定义类型,然后这些可以从脚本代码被调用。想使用这些功能必须有QScriptEngine:: FunctionSignature()的家长签字。然后你可能会传递函数作为参数传递给newFunction()。这里是一个函数返回它的前两个参数的和的一个例子:
QScriptValue myAdd(QScriptContext *context, QScriptEngine *engine)
{
QScriptValue a = context->argument(0);
QScriptValue b = context->argument(1);
return a.toNumber() + b.toNumber();
}
若要公开这个功能的脚本代码,可以将其设置为全局对象的一个属性:
QScriptValue fun = myEngine.newFunction(myAdd);
myEngine.globalObject().setProperty("myAdd", fun);
一旦做到这一点,脚本代码可以用完全相同的方式调用你的函数,并作为一个“正常”的脚本函数:
QScriptValue result = myEngine.evaluate("myAdd(myNumber, 1)");
长时间运行脚本
如果您需要解释从主(GUI)线程可能长时间运行的脚本,你应该先调用setProcessEventsInterval(),以确保该图形用户界面保持响应。你可以通过调用abortEvaluation()终止当前正在运行的脚本。你可以通过调用isEvaluating()确定引擎是否正在运行的脚本。
垃圾回收
Qt的脚本对象可以被垃圾回收,若是这样,他们将不再允许被引用。不过没有人知道自动垃圾回收将会何时发生。
CollectGarbage()函数可以被调用来显式地请求垃圾回收。
reportAdditionalMemoryCost()函数可以被调用,以表明一个Qt Script对象占用的并非是由脚本环境管理的内存。报告的额外成本使得垃圾回收器更容易被触发。这可能是有用的,例如在许多Qt规则中,原生的Qt Script对象会被分配。
核心调试/跟踪功能
自Qt的4.4以来,您可以通过QScriptEngineAgent接口获取有关的脚本执行(如脚本函数调用和语句的执行)的事件通知;看到setAgent()函数。这可以被用来实现调试和QScriptEngine的分析。
更多详情,请见QScriptValue,QScriptContext和QScriptEngineAgent等类的说明文档。