【问题标题】:QQuickFrameBufferObject causes crash in PySide2QQuickFrameBufferObject 导致 PySide2 崩溃
【发布时间】:2020-09-09 00:01:44
【问题描述】:

我正在尝试创建一个简单的QQuickFrameBufferObject,以便在 Qt Quick 中呈现一些自定义的 opengl 纹理。所以我决定用 PySide2 测试一下。这是一个简单的实现:

from PySide2.QtQuick import QQuickFramebufferObject
from PySide2.QtGui import QOpenGLFramebufferObjectFormat, QOpenGLFramebufferObject
from PySide2.QtCore import QSize, Qt

class FboRenderer(QQuickFramebufferObject.Renderer):
    def __init__(self, parent=None):
        super().__init__(parent)
        print("Creating renderer")

    def createFrameBufferObject(self, size):
        format = QOpenGLFramebufferObjectFormat()
        format.setAttachment(QOpenGLFramebufferObject.Depth)
        return QOpenGLFramebufferObject(size, format)

    def synchronize(self, item):
        print("Synchronizing")

    def render(self):
        print("Rendering")

class OpenGLCanvas(QQuickFramebufferObject):
    def __init__(self, parent=None):
        super().__init__(parent)

    def createRenderer(self):
        return FboRenderer()

然后在我使用的 QML 中使用它:

    qmlRegisterType(OpenGLCanvas,"OpenGLCanvas", 1, 0, "OpenGLCanvas")
import QtQuick 2.12
import QtQuick.Window 2.12
import OpenGLCanvas 1.0

Window{
    id: win
    visible: true

    OpenGLCanvas{
        anchors.fill: parent
    }
}

现在应用程序运行并显示“正在创建渲染器”,但几秒钟后它崩溃了。

【问题讨论】:

    标签: python qt qt5 qtquick2 pyside2


    【解决方案1】:

    问题在于FboRenderer() 是一个局部变量,会立即销毁,因此它也会销毁 C++ 对象,从而导致分段错误,因为访问了未保留的内存。

    另一方面,您在createFrameBufferObject 中有错字,因为它必须是createFramebufferObject,这也揭示了类似于初始错误的错误,为此解决方案类似。

    class FboRenderer(QQuickFramebufferObject.Renderer):
        def __init__(self):
            super().__init__()
            print("Creating renderer")
            self._fbos = []
    
        def createFramebufferObject(self, size):
            fmt = QOpenGLFramebufferObjectFormat()
            fmt.setAttachment(QOpenGLFramebufferObject.Depth)
            fbo = QOpenGLFramebufferObject(size, fmt)
            self._fbos.append(fbo)
            return fbo
    
        def synchronize(self, item):
            print("Synchronizing")
    
        def render(self):
            print("Rendering")
    
    
    class OpenGLCanvas(QQuickFramebufferObject):
        def __init__(self, parent=None):
            super().__init__(parent)
            self._renderer = None
    
        def createRenderer(self):
            if self._renderer is None:
                self.renderer = FboRenderer()
            return self.renderer
    

    【讨论】:

    • @daljit97 嗯,我看到你知道 C++,所以解释会更容易。您已经看到这两个方法都返回一个指针,因此负责管理动态内存的是调用这些方法的类,并且他们这样做了。检查源代码我发现createRenderer() 只被调用一次,而createFramebufferObject() 被调用了n 次,所以我创建了一个实例或使用一个列表。
    猜你喜欢
    • 1970-01-01
    • 2018-01-23
    • 2020-12-02
    • 2013-11-11
    • 2011-01-24
    • 2015-02-23
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多