繁体   English   中英

在 PyObject_NEW 创建时初始化非平凡的 class 成员

[英]Initialize nontrivial class members when created by PyObject_NEW

我有一个 Python object 指代一个 C++ object。

Header:

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>

typedef struct {
    PyObject_HEAD
    FrameBuffer frame_buffer;
} PyFrameBuffer;

extern PyTypeObject PyFrameBuffer_type;

extern PyObject* PyFrameBuffer_NEW(size_t width, size_t height);

C++ FrameBuffer class 如下:

class FrameBuffer {
public:
    explicit FrameBuffer(const size_t width, const size_t height);

    // ...

private:
    size_t m_width;
    size_t m_height;
    std::vector<Pixel> m_pixels;
};

Pixel是一个简单的 class 几个普通类型元素。

PyFrameBuffer_NEW() function 如下:

PyObject* PyFrameBuffer_NEW(size_t width, size_t height)
{
    auto* fb = (PyFrameBuffer*) PyObject_NEW(PyFrameBuffer, &PyFrameBuffer_type);

    if (fb != nullptr)
    {
        fb->frame_buffer = FrameBuffer(width, height);
    }

    return (PyObject*) fb;
}

此代码崩溃:

fb->frame_buffer分配有未定义的值( fb->frame_buffer.m_pixels.size()未定义)。

fb->frame_buffer赋值期间,在m_pixels中有一个未定义数量的Pixel被重新分配。

因此,它崩溃了。

这段代码似乎有效

/// ...
    if (fb != nullptr)
    {
        FrameBuffer fb_tmp(width, height);
        std::memcpy(&fb->frame_buffer, &fb_tmp, sizeof(FrameBuffer));
    }
// ...

但我怀疑这不是解决这个问题的正确方法(我怀疑 fb_tmp 中的Pixel s 在fb_tmp之外被取消分配。

  • 解决这个问题的正确方法是什么?
  • 关于如何在 CPython 中公开复杂的 object 是否有一种众所周知的方法?

我已经成功地使用了类似于

typedef struct {
    PyObject_HEAD
    FrameBuffer *frame_buffer;
} PyFrameBuffer;

然后

if (fb != nullptr)
{
    fb->frame_buffer = new FrameBuffer( ... );
}

但是您必须明确删除 object。 您需要将tp_dealloc() function添加到PyFrameBuffer初始化中,以删除 C++ FrameBuffer object:

delete fb->frame_buffer;

还:

当您使用 C++ 创建 Python 扩展模块时,您正在链接代码的 C++ 运行时库。 如果多个模块使用 C++,则它们必须使用完全相同的 C++ 运行时库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM