PyQt/PySide: QObject のスコープに注意

2011 年 6 月 19 日 はてなブックマークへ追加 はてなブックマーク - PyQt/PySide: QObject のスコープに注意 Bookmark this on Delicious

PyQt4 や PySide は C++ で GUI を書く気がなくなるぐらい便利なライブラリなのだけど、 厄介な問題もある。例えば、変数のスコープ。

Qt は C++ のライブラリなので、関数内で作った変数(自動変数)がスコープを抜ける時に 削除されることを上手く利用している。

int Foo::foo()
{
    QDialog dlg(this);
    return dlg.exec();
}

上のコードで QDialog のインスタンスは exec() 後に勝手に消えてくれるのだが、 Python ではそうは行かない。

def foo(self):
    dlg = QDialog(self)
    return dlg.exec_()

親ウィジェットの selfdlg を所有してしまうため、 dlg は GC の対象にならない。

次は segfault するかもしれない例。

def draw():
    pixmap = QPixmap()
    painter = QPainter(pixmap)
    # ... hack hack ...
    painter.end()
    return pixmap

painter.end() の前に例外が起きて draw() を抜けると、 pixmappainter は GC の対象になる。 pixmap が先に削除されたりすると大変だ。

QPaintDevice: Cannot destroy paint device that is being painted
Segmentation fault
# gdb ;)

painter のデストラクタで painter.end() しようとしても pixmap が無くなっているのだから。

コメント

blog comments powered by Disqus