I have a Python object referring to a 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);
The C++ FrameBuffer
class is following:
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
is a simple class of few plain type elements.
The PyFrameBuffer_NEW()
function is following:
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;
}
This code crashs:
fb->frame_buffer
is allocated with undefined values (fb->frame_buffer.m_pixels.size()
is undefined).
During fb->frame_buffer
assignment, there is a deallocation of an undefinied number of Pixel
in m_pixels
.
And so, it crash.
This code seems to works:
/// ...
if (fb != nullptr)
{
FrameBuffer fb_tmp(width, height);
std::memcpy(&fb->frame_buffer, &fb_tmp, sizeof(FrameBuffer));
}
// ...
But I suspect this is not the proper way to solve this issue (I suspect Pixel
s in fb_tmp
are desallocated outside the scope.
I've successfully used code similar to
typedef struct {
PyObject_HEAD
FrameBuffer *frame_buffer;
} PyFrameBuffer;
and then
if (fb != nullptr)
{
fb->frame_buffer = new FrameBuffer( ... );
}
But you have to account for deleting the object explicitly. You'll need to add a tp_dealloc()
function to your PyFrameBuffer
initialization that deletes the C++ FrameBuffer
object:
delete fb->frame_buffer;
Also:
When you use C++ to create a Python extension module, you're linking in your code's C++ runtime libraries. If more than one module uses C++, they all have to use the exact same C++ runtime libraries.