在我的Qt应用程序中,我试图将较大的整数值从C++代码传递给QML。
在我的C++中,我有一个Q_PROPERTY(int ...),但显然int有时不足以满足我的应用程序的需要,并且溢出。
我可以在QML中使用长类型或无符号类型吗?动态大小的int类型如何?
从QML文档中,我所能找到的都是int,范围为“-2000000000到2000000000左右”。
任何帮助表示赞赏! =)
最佳答案
我觉得您的问题很有趣,因为它一开始看起来很琐碎,尽管在获取答案的方式上却提出了很多观点。
我假设您想将64位整数从C++传递给QML。我稍后解释。
用于64位整数的QML基本类型
没有64位整数QML basic type,因此您不能期望将C++值转换并存储在这样的不存在的QML类型属性中。如文档中所述,Qt模块可以扩展可用类型的列表。我们甚至可以想到一个将来可以添加自己的类型的 future ,但如今不行:
Currently only QML modules which are provided by Qt may provide their own basic types, however this may change in future releases of Qt QML.
有人可能会认为,在64位平台上编译其应用程序应该可以完成这项工作,但不会改变任何事情。关于这个问题有a lot of answers。为了清楚起见,这是在同一台计算机上使用32位和64位编译器对结果进行的比较:
在具有32位编译器(mingw53)的64位系统(Windows 7 64位)的计算机(64位处理器:Core i7)上,我已经
4 = sizeof(int) = sizeof(long) = sizeof(int*) = sizeof(size_t)
我把
size_t
弄清楚了,它不能用于表示文件大小,不是its purpose。在同一系统上使用64位编译器(msvc2017,x64):
4 = sizeof(int) = sizeof(long)
8 = sizeof(int*) = sizeof(size_t)
使用64位编译器不会更改
sizeof(int)
,因此认为int
与int*
的大小相同显然是错误的。在您的情况下,您似乎要存储文件大小,而32位不足以表示文件大小。因此,如果我们不能依靠
int
来执行此操作,则应使用哪种类型?文件大小类型大小
现在,我认为64位整数应该足够了,并且是存储文件大小的正确方法。但这是真的吗?根据cplusplus.com,此类型为std::streampos。如果您在cppreference.com上查找详细信息,则会发现
std::streampos
是std::fpos
的特化,并描述了其典型实现:Specializations of the class template
std::fpos
identify absolute positions in a stream or in a file. Each object of typefpos
holds the byte position in the stream (typically as a private member of typestd::streamoff
) and the current shift state, a value of typeState
(typicallystd::mbstate_t
).
std::streamoff的实际类型可能是64位有符号整数:
The type
std::streamoff
is a signed integral type of sufficient size to represent the maximum possible file size supported by the operating system. Typically, this is atypedef
tolong long
.
另外,在同一页面上,您可以阅读:
a value of type
std::fpos
is implicitly convertible tostd::streamoff
(the conversion result is the offset from the beginning of the file).a value of type
std::fpos
is constructible from a value of typestd::streamoff
让我们再看看32位或64位目标平台所具有的功能。
使用32位编译器
8 = sizeof(long long) = sizeof(std::streamoff)
16 = sizeof(std::streampos)
它表明,显然,比现在知道文件大小所需的信息更多的信息存储在
std::streampos
中。在同一系统上使用64位编译器:
8 = sizeof(long long) = sizeof(std::streamoff)
24 = sizeof(std::streampos)
sizeof(std::streamoff)
的值未更改。可能有。在两种情况下,它都必须足够大才能存储文件大小。您可能需要使用std::streamoff
在C++端存储文件大小。您不能依靠它是64位。让我们假设有人想冒一个风险,即假设它是64位,如这些示例所示:仍然存在将其作为基本类型传递给QML以及可能传递给Javascript引擎的问题。
尽管如此,在QML中使用了接近64位
如果只需要将大小显示为以字节为单位的数字,则UI中将需要文本表示。您可以坚持这个想法,使用字符串,而不必传递整数值。
如果您需要使用Javascript在QML方面进行算术运算,除非您不使用核心语言进行算术运算,否则您可能会碰到Javascript
Number
的53 bit barrier。在这里,如果您假设文件大小不能大于2 ^ 53,则可以使用
double
。您必须知道this answer中所述如何在目标平台上处理double
类型,如果足够幸运的话,它将具有不损失53位整数值的存储能力。之后,您可以直接在Javascript中对其进行操作,并且保证可以正常运行,至少在ECMA 262版本8中如此。现在可以了吗?我们可以对小于2 ^ 53的任何文件使用 double 吗?
好吧……Qt不一定实现ECMAScript的最新规范,而是使用several implementations。
在Webviews中,它确实使用了rather common implementation。
在QML中,它使用基于ECMA 262版本5的自己的,未记录的内置Javascript引擎。此版本的ECMA没有明确提及一个值,所有较小的整数值都必须保证存储在
Number
中。这并不意味着它将无法正常工作。即使已提及,该实现也仅基于规范,并不要求合规。您可能会发现自己很不幸地需要长时间工作,然后在更新的Qt版本中发现它不再起作用。看来必须做出许多假设。在基于它的软件的整个生命周期中,所有这些可能都是并且可能会保持正确。因此,这是应对风险的问题。
有没有办法降低想要降低的风险?
不冒一点点正确性的风险
我看到两条主要路径:
提示:bittorent protocol使用字符串来编码大小。
问题不仅限于QML属性
如果您使用Javascript对
Number
实例操作整数值,并将其用作QML信号的int
参数的参数,则可能会出现相同的问题。例如,声明这样的信号: signal sizeChanged(var newSize) // Number class (maybe 53 bit) integral value possible
可能处理以下情况肯定无法解决的情况:
signal sizeChanged(int newSize) // 32 bit int limitation
失败的一个例子是传递
(new Date()).getTime()
。这是相同的限制,不限于与QML进行C++属性交互。
关于c++ - Qt:QML Int溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25709429/