diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -488,39 +488,53 @@ } } +%inline %{ + +struct Py_buffer_RAII { + Py_buffer buffer = {}; + Py_buffer_RAII() {}; + Py_buffer &operator=(const Py_buffer_RAII &) = delete; + Py_buffer_RAII(const Py_buffer_RAII &) = delete; + ~Py_buffer_RAII() { + if (buffer.obj) + PyBuffer_Release(&buffer); + } +}; + +%} + // These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, // and fixed so they will not crash if PyObject_GetBuffer fails. // https://github.com/swig/swig/issues/1640 +// +// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper, +// doing it right away is not legal according to the python buffer protocol. %define %pybuffer_mutable_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + res = PyObject_GetBuffer($input, &view.buffer, PyBUF_WRITABLE); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.buffer.len; + buf = view.buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size/sizeof($*1_type)); } %enddef %define %pybuffer_binary(TYPEMAP, SIZE) -%typemap(in) (TYPEMAP, SIZE) { +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { int res; Py_ssize_t size = 0; const void *buf = 0; - Py_buffer view; - res = PyObject_GetBuffer($input, &view, PyBUF_CONTIG_RO); + res = PyObject_GetBuffer($input, &view.buffer, PyBUF_CONTIG_RO); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } - size = view.len; - buf = view.buf; - PyBuffer_Release(&view); + size = view.buffer.len; + buf = view.buffer.buf; $1 = ($1_ltype) buf; $2 = ($2_ltype) (size / sizeof($*1_type)); }