关于QT在release模式下对QML和JS文件的优化问题

原创
2020/12/19 14:11
阅读数 238

直接上结论

  1. 经过测试,该问题只在QT5的某几个版本会出现。本人电脑上装的5.5和5.15,这两个版本没有该问题,我在公司电脑上装的5.12,确实会存在该问题。我通过查看一些qrc的编译输出文件而得出,应该是5.12前后的几个版本,QT经过了两次优化所遗留的问题。
  2. 问题如下:
    • 在QT项目中添加qrc资源文件
    • 在该资源文件中添加以.js结尾的文件
    • 在cpp中使用QFile读取该js文件,并输出文件内容

经过以上步骤编译运行应该能够看到结果: 如果你使用的刚好是QT5.12(具体是哪几个版本我不清楚,这里用5.12举例),那么在debug模式下该js文件能够正常open并读取全部内容。但是切换到release模式下仍然可以正常open(说明该路径存在),但读取的内容为空。

解决方案

将该js文件的后缀修改,或者添加新的后缀,重新qmake并重新编译,在release模式下就能正常open并读取全部内容。
但该解决方案仍然有两个注意点:

  1. 文件后缀除了不能为js以外,也不能为qml。这两种后缀的文件在QT5.12上只能被QQmlEngine所加载,不能使用QFile读取。
  2. 如果后缀不为.js,那么该文件将不能在qml中被import。 也即是说,如果你想正常的编写QML代码和JS脚本,并且正常的使用QQmlEngine加载,那么后缀只能是.qml和.js,此时不能在cpp中使用QFile读取。如果你想在cpp中使用QFile读取文件内容,那么后缀就不能使用这两个,此时该文件不能被QQmlEngine加载或在QML中导入(仅针对QT5.12及其邻近的几个有问题的版本)。

由于个人已经使用了QT5.15版本,并且也没有遇到过既需要在cpp中读取,也需要在QML中加载的需求,所以没有在该问题上深究。如果你有这种需求,这里很抱歉的告诉你不能为你提供解决方案,只能建议你更换版本。

分析

QT5.5和QT5.15的qrc文件在release模式下编译输出文件并不一样,所以可以证明qrc文件至少经历过两次优化,所以这里将会分析QT5.5和QT5.15两个版本。

  1. 添加一个qml.qrc文件,并在该文件中添加test.js文件,编写如下内容:
function func() {
    console.log("aaaa");
}
  1. 此时目录结构如下:

在QT5.5和QT5.15的debug模式下编译,并进入编译输出目录,都可以找到一个名为qrc_qml.cpp的文件
QT5.5

QT5.15

打开该文件之后两个版本的内容基本一样(有细微差别但不大)。在该文件中可以找到调用qRegisterResourceData函数的地方,该函数中的其中两个参数qt_resource_name和qt_resource_data分别保存了test.js的文件路径和文件内容,这即是我们能使用QFile打开并读取test.js内容的关键。
QT5.5

QT5.15

该文件中有一个名为initializer的结构体,该结构体只是利用静态对象的初始化来调用qRegisterResourceData函数的而已,可以先不用管,有兴趣可以查一查,后面我可能会单开一章来单独讨论利用C++语言的特性来做一些便利性编程,以及QT库和我自己利用这些特性实现的一些功能。
现在我们使用release编译,在QT5.5的输出目录下面仍然可以找到qrc_qml.cpp文件,并且里面的内容和debug模式一模一样,这就是为什么在5.5版本上并不存在我上面说的那种问题的原因。

同样release模式,我们打开QT5.15版本的输出目录,现在你就找不到qrc_qml.cpp文件了,取而代之的是test_js.cpp、qmlcache_loader.cpp和qrc_qml_qmlcache.cpp这三个文件。test_js.cpp和qmlcache_loader.cpp这两个文件的作用是使用QQmlEngine加载qml文件和在QML中导入js的关键,它们注册的内容不能被QFile读取。

我们打开qrc_qml_qmlcache.cpp这个文件,发现里面的内容和debug模式下qrc_qml.cpp的内容一模一样,这也是为什么QT5.15在release模式下也能正常读取的原因。但是为什么QT5.5和QT5.15的输出文件不一样,而且QT5.15还多此一举的原因,我觉得应该是QT的两次优化的问题(这里我不清楚具体的优化版本,所以暂定为QT5.12)。
但是, 上面我们看到QT5.15中有一个名为qrc_qml_qmlcache.cpp的文件,和qrc_qml.cpp的内容一模一样,又多出了两个test_js.cpp和qmlcache_loader.cpp文件。这其实是5.15版本的第二次优化导致的问题。如果手上有5.12版本的童鞋,就可以看到在release的输出目录并没有qrc_qml_qmlcache.cpp文件(如果有其他后缀不为.js或者.qml的文件的话,这个文件其实也会存在),那么这个时候你打开qmlcache_loader.cpp文件你仍然可以找到qRegisterResourceData这个函数,但是这个函数的第三个参数仍然是文件路径,但第四个参数指定的内容为空,这就是为什么QFile能够正常open文件,但是读取内容为空的原因。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部