QML是在编译时被翻译成本机代码,还是在运行时被解释为JavaScript在web浏览器中的运行方式

Is QML translated into native code at the compilation time or is it interpreted at runtime the way JavaScript is ran in web browsers?

本文关键字:web JavaScript 浏览器 运行方式 解释 翻译 编译 本机代码 QML 运行时      更新时间:2023-10-16

QML是在编译时被翻译成本机代码,还是在运行时几乎像在web浏览器中运行JavaScript一样被解释?

AFAIK,Qt文档中似乎没有直接而详细的解释,但一些Qt黑客试图解释它:

QML被编译为优化的类似字节码的流JavaScript表达式通过优化的计算器表达式。

还有相关的QTBUG任务Qt快速启动时间有待提高;运行之间缓存编译的QML

我的理解是,QML的状态还没有完全解决,工程师们也没有宣布它是固定的,所以他们可以自由地在未来改进它。

ATM,最好的建议是将C++与QML混合,将所有应用程序逻辑都用C++表示,并用QML表示,但最好将其划分为较小的QML文件,而不是单个大型QML文件。

有了Qt 5.3和企业许可证,实际上有一种方法可以预编译它。

https://doc.qt.io/QtQuickCompiler/

这对于苹果不允许JIT代码生成的iOS非常有用。

我刚刚有同样的问题,几年后的情况如下:

现状(5.15 Qt)

Qt5中最先进的技术是使用提前QML编译。这使用了QuickCompiler;在Qt 5.3中为商业许可证持有者引入,在Qt 5.11";(来源)。从QtQuickCompiler的旧文档中,它的实际功能变得更加清晰:

[没有QtQuickCompiler,]流行的实时(JIT)编译技术用于[从QML]动态生成机器代码,从而加快JavaScript和QML绑定表达式的执行。

不幸的是,这种方法有一些缺点:[…]一些平台版本,如iOS或Windows RT,不允许动态生成机器代码。[…]

编译的QtQuick[通过QtQuickCompiler]是解决这些问题的一个优雅的解决方案:.qml文件以及附带的.js文件可以转换为中间C++源代码。使用传统编译器编译后,代码将链接到应用程序二进制文件中。

这种使用QtQuickCompiler的提前编译会产生与实时(JIT)编译在运行时从QML产生的字节码相同的字节码。QtQuickCompiler确实产生了";中间C++源代码";,但这只是C++数据结构中的字节码,要嵌入到生成的C++可执行文件中。我测试了它;要亲自查看,只需在启用QtQuickCompiler的情况下构建一个QtQuick项目,然后在构建目录中打开为{filename}.qml生成的文件{filename}_qml.cpp。它看起来是这样的:

// /{filename}.qml
namespace QmlCacheGeneratedCode {
    namespace _0x5f__main_qml {
        extern const unsigned char qmlData alignas(16) [] = {
            0x71,0x76,0x34,0x63,0x64,0x61,0x74,0x61,
            0x20,0x0,0x0,0x0,0x4,0xc,0x5,0x0,
            // … many many more lines …
            0x40,0x0,0x40,0x1,0x40,0x0,0xf0,0x1,
            0x0,0x0,0x0,0x0
        };
    }
}

因此,在Qt5中,QML既没有在编译时被翻译成本机[C++]代码,也没有在运行时被解释。相反,它会提前编译为字节码。然后,这个字节码将在一个用于JavaScript的小型虚拟机中运行,类似于JVM中使用Java字节码所做的操作。总是需要虚拟机,因为从QML/JavaScript这样的弱类型语言编译机器代码是不可能的。

当QtQuickCompiler和带有缓存的JIT编译都不可用时;QML提供了一个解释器以允许充分使用QML,但这是以较长的执行时间为代价的"(来源)

未来情况(第6季度)

据计划,Qt6的未来版本确实将包括QML翻译成本机C++代码,然后像编译任何其他C++代码一样进行编译:

支持将QML编译为高效的C++和本机代码通过强大的类型和更简单的查找规则,我们可以将QML转换为高效的C++和本机代码,从而显著提高运行时性能。(来源)

我不得不说,这听起来很棒:)

编译的语言和解释的语言之间有很大的区别。QML文档由QML运行时进行解释。从某种意义上说,可以说它是像JavaScript一样执行的。

QML运行时包括QML引擎、JavaScript引擎和绑定到Qt框架的机制。

Qt快速编译器™Qt 6.3

新的Qt快速编译器将由两个组件组成:QML类型编译器和QML脚本编译器。QML类型编译器将把QML对象结构编译成C++类。QML脚本编译器将把应用程序的QML文件中的函数和表达式编译成C++代码。尽可能多,因为JavaScript的性质会设置一些限制。如果某些语句无法编译,则将使用常规解释和缓存。。。。。(来源)