QScriptEngine类提供用于解释的Qt Script代码的环境

0 1312
索鸟 2020-08-19
需要:0索币
  1. QScriptEngine myEngine;
  2. QScriptValue three = myEngine.evaluate("1 + 2");


evaluate()返回一个QScriptValue保存的解释结果。该QScriptValue类提供函数计算结果并转换为不同的C++类型(例如QScriptValue:: toString()QScriptValue:: toNumber())。

 

例二:
下面的代码片段显示了一个脚本函数被定义,然后从C++中调用使用QScriptValue::()的调用的例子:

  1. QScriptValue fun = myEngine.evaluate("(function(a, b) { return a + b; })");
  2. QScriptValueList args;
  3. args << 1 << 2;
  4. QScriptValue threeAgain = fun.call(QScriptValue(), args);


如可以从上面的代码段中可以看出,一个脚本被以字符串的形式提供给解释引擎。加载脚本的一种常见方法是通过读取一个文件的内容,并通过它来evaluate(),如下代码:

  1. QString fileName = "helloworld.qs";
  2. QFile scriptFile(fileName);
  3. if (!scriptFile.open(QIODevice::ReadOnly))
  4. // handle error
  5. QTextStream stream(&scriptFile);
  6. QString contents = stream.readAll();
  7. scriptFile.close();
  8. myEngine.evaluate(contents, fileName);


上面我们通过文件名作为第二个参数来evaluate()。这并不影响解释的方式,第二个参数是用来识别脚本用于调试目的的general-purpose字符串(例如,我们的文件名现在将要通过uncaughtExceptionBacktrace() involving到脚本)。

 

引擎配置 
globalObject()函数返回与脚本引擎相关联的全局对象。全局对象的属性可从任何脚本代码访问(也就是说,它们是全局变量)。通常情况下,解释脚本之前,你会希望通过添加一个或多个属性的全局对象来配置脚本引擎:

  1. myEngine.globalObject().setProperty("myNumber", 123);
  2. ...
  3. QScriptValue myNumberPlusOne = myEngine.evaluate("myNumber + 1");


添加自定义属性的脚本环境或提供脚本API是脚本相对于应用程序定制的标准方法之一。通常这些自定义属性有由newQObject()newobject()函数,或者通过newFunction(创建构造函数)创建的对象。

 

脚本异常 
evaluate()可以抛出一个脚本异常(如由于语法错误);在这种情况下,返回值是一个被抛出(通常是一个错误的对象)的值。您可以检查是否解释器通过调用hasUncaughtException()导致了异常。在这种情况下,你可以调用的错误对象的toString()来获取错误消息。对于目前未捕获的异常,也可通过uncaughtException()。调用clearExceptions()将导致任何未捕获的异常被清除。

  1. QScriptValue result = myEngine.evaluate(...);
  2. if (myEngine.hasUncaughtException()) {
  3. int line = myEngine.uncaughtExceptionLineNumber();
  4. qDebug() << "uncaught exception at line" << line << ":" << result.toString();
  5. }


checkSyntax()函数可以被用来确定是否代码已经有效地传递到evaluate()

 

脚本对象的创建 
使用newobject()来创建一个标准的Qt Script对象;这是相当于C++的new Object()。您可以使用该对象的特定功能,在QScriptValue操纵脚本对象(例如QScriptValue::setProperty())。同样,使用newArray()来创建一个Qt脚本数组对象。使用newDate()来创建一个日期对象,newRegExp()来创建一个RegExp对象等都是被允许的。

QObject的整合 
使用newQObject()来包装一个QObject的(或子类)的指针。newQObject()返回一个代理脚本对象、特性、子类、信号或QObject的槽,它可作为代理对象的属性。不需要任何绑定代码,因为它是使用Qt元对象系统动态地进行管理。

  1. QPushButton button;
  2. QScriptValue scriptButton = myEngine.newQObject(&button);
  3. myEngine.globalObject().setProperty("button", scriptButton);
  4. myEngine.evaluate("button.checkable = true");
  5. qDebug() << scriptButton.property("checkable").toBoolean();
  6. 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()。这里是一个函数返回它的前两个参数的和的一个例子:

  1. QScriptValue myAdd(QScriptContext *context, QScriptEngine *engine)
  2. {
  3. QScriptValue a = context->argument(0);
  4. QScriptValue b = context->argument(1);
  5. return a.toNumber() + b.toNumber();
  6. }


若要公开这个功能的脚本代码,可以将其设置为全局对象的一个属性:

  1. QScriptValue fun = myEngine.newFunction(myAdd);
  2. myEngine.globalObject().setProperty("myAdd", fun);


一旦做到这一点,脚本代码可以用完全相同的方式调用你的函数,并作为一个正常的脚本函数:

QScriptValue result = myEngine.evaluate("myAdd(myNumber, 1)");

 

长时间运行脚本 
如果您需要解释从主(GUI)线程可能长时间运行的脚本,你应该先调用setProcessEventsInterval(),以确保该图形用户界面保持响应。你可以通过调用abortEvaluation()终止当前正在运行的脚本。你可以通过调用isEvaluating()确定引擎是否正在运行的脚本。

 

垃圾回收 
Qt的脚本对象可以被垃圾回收,若是这样,他们将不再允许被引用。不过没有人知道自动垃圾回收将会何时发生。 
CollectGarbage()函数可以被调用来显式地请求垃圾回收。 
reportAdditionalMemoryCost()函数可以被调用,以表明一个Qt Script对象占用的并非是由脚本环境管理的内存。报告的额外成本使得垃圾回收器更容易被触发。这可能是有用的,例如在许多Qt规则中,原生的Qt Script对象会被分配。

 

核心调试/跟踪功能 
Qt4.4以来,您可以通过QScriptEngineAgent接口获取有关的脚本执行(如脚本函数调用和语句的执行)的事件通知;看到setAgent()函数。这可以被用来实现调试和QScriptEngine的分析。

回帖
  • 消灭零回复
相关主题
2020年最新最新Kubernetes视频教程(K8s)教程 2
程序员转型之制作网课变现,月入过万告别996 1
索鸟快传2.0发布啦 1
两个不同网络的电脑怎么实现文件的互相访问呢? 1
网盘多账号登录软件 1
Java实战闲云旅游项目基于vue+element-ui 1
单点登录技术解决方案基于OAuth2.0的网关鉴权RSA算法生成令牌 1
QT5获取剪贴板上文本信息QT设置剪贴板内容 1
springboot2实战在线购物系统电商系统 1
python web实战之爱家租房项目 1
windows COM实用入门教程 1
C++游戏开发之C++实现的水果忍者游戏 1
计算机视觉库opencv教程 1
node.js实战图书管理系统express框架实现 1
C++实战教程之远程桌面远程控制实战 1
相关主题
PHP7报A non well formed numeric value encountered 0
Linux系统下关闭mongodb的几种命令分享 0
mongodb删除数据、删除集合、删除数据库的命令 0
Git&Github极速入门与攻坚实战课程 0
python爬虫教程使用Django和scrapy实现 0
libnetsnmpmibs.so.31: cannot open shared object file 0
数据结构和算法视频教程 0
redis的hash结构怎么删除数据呢? 0
C++和LUA解析器的数据交互实战视频 0
mongodb errmsg" : "too many users are authenticated 0
C++基础入门视频教程 0
用30个小时精通C++视频教程可能吗? 0
C++分布式多线程游戏服务器开发视频教程socket tcp boost库 0
C++培训教程就业班教程 0
layui的util工具格式时间戳为字符串 0
C++实战教程之远程桌面远程控制实战 1
网络安全培训视频教程 0
LINUX_C++软件工程师视频教程高级项目实战 0
C++高级数据结构与算法视频教程 0
跨域问题很头疼?通过配置nginx轻松解决ajax跨域问题 0