在 QIODevice 子类中覆盖 readData 会返回不正确的结果
Posted
技术标签:
【中文标题】在 QIODevice 子类中覆盖 readData 会返回不正确的结果【英文标题】:Overriding readData in QIODevice subclass returns incorrect result 【发布时间】:2011-12-28 16:03:21 【问题描述】:我正在尝试在 PySide 中对 QFile 进行子类化以实现自定义读取行为。但是,从下面的简化代码中可以看出,即使子类的 readData 实现只是调用了父类的 readData 函数,返回的数据也是不正确的。将其他 QIODevice 子类化(例如 QBuffer)也会导致返回值不正确。有没有人成功地将 QIODevice 子类化?
from PySide import QtCore
class FileChild1(QtCore.QFile):
pass
class FileChild2(QtCore.QFile):
def readData(self, maxlen):
return super(FileChild2, self).readData(maxlen)
f1 = FileChild1('test.txt')
f1.open(QtCore.QIODevice.ReadWrite|QtCore.QIODevice.Truncate)
f1.write('Test text for testing')
f1.seek(0)
print 'FileChild1: ', repr(f1.read(50))
f2 = FileChild2('test2.txt')
f2.open(QtCore.QIODevice.ReadWrite|QtCore.QIODevice.Truncate)
f2.write('Test text for testing')
f2.seek(0)
print 'FileChild2: ', repr(f2.read(50))
>>> FileChild1: PySide.QtCore.QByteArray('Test text for testing')
>>> FileChild2: PySide.QtCore.QByteArray('─ Q ►│A☻ @ p¼a☻Test text for testing\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
【问题讨论】:
在Qt原C++版本中,readData有如下签名qint64 QIODevice::readData ( char * data, qint64 maxSize )
,其中数据被读入char数组并返回长度。在 PySide 和 PyQt 中,读取的数据直接以字符串形式返回。这种差异可能与它有关吗?
这在 PyQt4 中按预期工作(PyQt4:4.8.6,Qt:4.7.4)。也许是 PySide 中的错误?
【参考方案1】:
我用 PyQt 4.8 和 PyQt 4.9 用 Python 2.7.2 / Qt 4.8.0 测试了你的脚本,在这两种情况下它都会产生以下输出:
FileChild1: 'Test text for testing'
FileChild2: 'Test text for testing'
所以readData
根据PyQt4 docs 返回一个字节字符串。
将 PySide 1.0.9 与 Python 2.7.2 / Qt 4.8.0 一起使用,我得到以下输出:
FileChild1: PySide.QtCore.QByteArray('Test text for testing')
FileChild2: PySide.QtCore.QByteArray('')
不知道为什么 PyQt4 和 PySide 之间的返回类型存在差异,但 PySide 中显然存在某种错误。
有一个错误报告 here 看起来可能有点相关,但不是特别新(PySide 1.0.7)。
【讨论】:
存在这个bug实在是太可惜了,我宁愿用PySide,但是看起来我别无选择。【参考方案2】:PySide 的 bug 来自 shiboken,即:qint64 在 QIODevice 中用作偏移类型,但 qint64 在 Python 2.x 中映射为“int”,而不是“long”。当 qint64 的值大于 qint32 时,读取该值会导致 Python 2.x 抛出 OverflowError。 当使用 qint64 作为 Slot/Signal/Property 或任何 Qt 元类型与 Python 通信 Qt C++ 代码时,会发生类似的溢出错误。
我也在寻找绕过这个问题的解决方案。
【讨论】:
【参考方案3】:在 Qt5 和 PySide2 上也非常有效。我们正在调查。
【讨论】:
以上是关于在 QIODevice 子类中覆盖 readData 会返回不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章