LINUX.ORG.RU

[python, PyQT?] Переменная удаляется, возвращаемое значение портится


0

1

Не знаю, специфична ли эта вещь для всего Python или только для PyQt, но у меня проявилось при использовании PyQt.

def createimg():
    pixels = '...' # пиксели в строковой переменной
    return QtGui.QImage(pixels, 158, 54, QtGui.QImage.Format_RGB32)

Таким образом из функции возвращается объект QImage, но pixels в нём уже нет. Проверяется путем сохранения картинки методом save(). Сохраняется рябь вместо изображения.

Как понимаю, здесь в функции в конструктор QImage передаётся указатель на строку pixels, соответственно, когда при возврате происходит выход из функции переменная pixels удаляется, указатель становится невалидным и проявляется наблюдаемый эффект.

Решается таким костылём:

def createimg():
    pixels = '...' # пиксели в строковой переменной
    return QtGui.QImage(pixels, 158, 54, QtGui.QImage.Format_RGB32), pixels

Т.е. вместе с объектом возвращаем и источник пикселей, чтобы он не удалился. Есть ли способы прямее?

А вообще в документации по Qt, про исползуемый тобой коструктор явно говорится: «The buffer must remain valid throughout the life of the QImage and all copies that have not been modified or otherwise detached from the original buffer. The image does not delete the buffer at destruction.»

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

loadFromData хочет данные в одном из форматов изображений. А у меня там просто набор пикселей.

Цитата ясна, тут скорее смущает тот факт, что python удаляет переменную хотя она еще используется в некотором объекте. Вот она, тёмная сторона сборщиков мусора. В С++ в этом моменте всё более очевидно.

Olegymous ★★★
() автор топика
Ответ на: комментарий от Olegymous

Вот она, тёмная сторона сборщиков мусора. В С++ в этом моменте всё более очевидно.

Это не темная сторона, это очередная кривость PyQt, так как, судя по всему, он не увеличивает счетчик ссылок на pixels.

baverman ★★★
()
Ответ на: комментарий от zJes

Ты не прав. Такое поведение заложено в самом Qt.

Очевидно, Qt принимает массив байт, а не PyString, поэтому обертка могла бы и позаботиться о пользователе. Причем хуже никому бы не стало. Почему, используя питон, меня должны волновать плюсатые заморочки?

baverman ★★★
()
Ответ на: комментарий от zJes

Такое поведение заложено в самом Qt.

И если говорить про поведение, то на C++ можно написать что-нибудь в духе:

Gui::QImage("...", ...)

А в PyQt хренушки, и про приемственность какого поведения идет речь?

baverman ★★★
()
Ответ на: комментарий от baverman

> Gui::QImage("...", ...)

Вот я не уверен...
Конструктор принимает uchar * data, при выходе из блока, где создается этот имидж в лучшем случае ждем сегфолт. То же самое и для PyQt, пока работаешь внутри блока, все ок. Хотя, если модифицировать имидж, то вроде должна будет создаться копия буфера.

zJes ★★
()
Ответ на: комментарий от zJes

Вот я не уверен...

Я тоже не уверен, на стеке или в секции данных будет аллоцирована эта строка, поэтому такой пример:

Выделяем в куче место для данных и передаем в QImage — все отлично работает, даже при выходе из области видимости (правда будет утечка), но на качество картинки это никак не повлияет.

А в PyQt заставляет делать O_o WTF?

baverman ★★★
()

А если использовать PySide вместо PyQt?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.