Skip to content

Commit

Permalink
Merge pull request #4869 from N-Dekker/Bridge-NumPy-PyBuffer-API
Browse files Browse the repository at this point in the history
Remove unnecessary PyBuffer_Release calls, and other "Bridge/NumPy"  style improvements
  • Loading branch information
thewtex authored Oct 7, 2024
2 parents bf0ed18 + aa2e259 commit 89bb76b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 30 deletions.
15 changes: 6 additions & 9 deletions Modules/Bridge/NumPy/include/itkPyBuffer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@


#include "itkImportImageContainer.h"
#include <memory> // For unique_ptr.

namespace itk
{
Expand Down Expand Up @@ -56,11 +57,9 @@ PyBuffer<TImage>::_GetArrayViewFromImage(ImageType * image)
len *= numberOfComponents;
len *= sizeof(ComponentType);

const int res = PyBuffer_FillInfo(&pyBuffer, nullptr, itkImageBuffer, len, 0, PyBUF_CONTIG);
PyBuffer_FillInfo(&pyBuffer, nullptr, itkImageBuffer, len, 0, PyBUF_CONTIG);
PyObject * const memoryView = PyMemoryView_FromBuffer(&pyBuffer);

PyBuffer_Release(&pyBuffer);

return memoryView;
}

Expand All @@ -80,15 +79,15 @@ PyBuffer<TImage>::_GetImageViewFromArray(PyObject * arr, PyObject * shape, PyObj
if (PyObject_GetBuffer(arr, &pyBuffer, PyBUF_ND | PyBUF_ANY_CONTIGUOUS) == -1)
{
PyErr_SetString(PyExc_RuntimeError, "Cannot get an instance of NumPy array.");
PyBuffer_Release(&pyBuffer);
return nullptr;
}

[[maybe_unused]] const std::unique_ptr<Py_buffer, decltype(&PyBuffer_Release)> bufferScopeGuard(&pyBuffer,
&PyBuffer_Release);

const Py_ssize_t bufferLength = pyBuffer.len;
void * const buffer = pyBuffer.buf;

PyBuffer_Release(&pyBuffer);

PyObject * const shapeseq = PySequence_Fast(shape, "expected sequence");
const unsigned int dimension = PySequence_Size(shape);

Expand All @@ -109,10 +108,9 @@ PyBuffer<TImage>::_GetImageViewFromArray(PyObject * arr, PyObject * shape, PyObj
}

const size_t len = numberOfPixels * numberOfComponents * sizeof(ComponentType);
if (bufferLength != len)
if (bufferLength < 0 || static_cast<size_t>(bufferLength) != len)
{
PyErr_SetString(PyExc_RuntimeError, "Size mismatch of image and Buffer.");
PyBuffer_Release(&pyBuffer);
SWIG_Py_DECREF(shapeseq);
return nullptr;
}
Expand Down Expand Up @@ -153,7 +151,6 @@ PyBuffer<TImage>::_GetImageViewFromArray(PyObject * arr, PyObject * shape, PyObj
output->SetNumberOfComponentsPerPixel(numberOfComponents);

SWIG_Py_DECREF(shapeseq);
PyBuffer_Release(&pyBuffer);

return output;
}
Expand Down
13 changes: 6 additions & 7 deletions Modules/Bridge/NumPy/include/itkPyVectorContainer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef itkPyVectorContainer_hxx
#define itkPyVectorContainer_hxx

#include <memory> // For unique_ptr.
#include <stdexcept>

namespace itk
Expand All @@ -42,11 +43,9 @@ PyVectorContainer<TElementIdentifier, TElement>::_array_view_from_vector_contain
Py_ssize_t len = vector->Size();
len *= sizeof(DataType);

const int res = PyBuffer_FillInfo(&pyBuffer, nullptr, vectorBuffer, len, 0, PyBUF_CONTIG);
PyBuffer_FillInfo(&pyBuffer, nullptr, vectorBuffer, len, 0, PyBUF_CONTIG);
PyObject * const memoryView = PyMemoryView_FromBuffer(&pyBuffer);

PyBuffer_Release(&pyBuffer);

return memoryView;
}

Expand All @@ -60,10 +59,12 @@ PyVectorContainer<TElementIdentifier, TElement>::_vector_container_from_array(Py
if (PyObject_GetBuffer(arr, &pyBuffer, PyBUF_CONTIG) == -1)
{
PyErr_SetString(PyExc_RuntimeError, "Cannot get an instance of NumPy array.");
PyBuffer_Release(&pyBuffer);
return nullptr;
}

[[maybe_unused]] const std::unique_ptr<Py_buffer, decltype(&PyBuffer_Release)> bufferScopeGuard(&pyBuffer,
&PyBuffer_Release);

const Py_ssize_t bufferLength = pyBuffer.len;
const void * const buffer = pyBuffer.buf;

Expand All @@ -75,10 +76,9 @@ PyVectorContainer<TElementIdentifier, TElement>::_vector_container_from_array(Py
const size_t numberOfElements = static_cast<size_t>(PyInt_AsLong(item));

const size_t len = numberOfElements * sizeof(DataType);
if (bufferLength != len)
if (bufferLength < 0 || static_cast<size_t>(bufferLength) != len)
{
PyErr_SetString(PyExc_RuntimeError, "Size mismatch of vector and Buffer.");
PyBuffer_Release(&pyBuffer);
return nullptr;
}
const auto * const data = static_cast<const DataType *>(buffer);
Expand All @@ -88,7 +88,6 @@ PyVectorContainer<TElementIdentifier, TElement>::_vector_container_from_array(Py
{
output->SetElement(ii, data[ii]);
}
PyBuffer_Release(&pyBuffer);

return output;
}
Expand Down
25 changes: 11 additions & 14 deletions Modules/Bridge/NumPy/include/itkPyVnl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef itkPyVnl_hxx
#define itkPyVnl_hxx

#include <memory> // For unique_ptr.
#include <stdexcept>

namespace itk
Expand All @@ -42,11 +43,9 @@ PyVnl<TElement>::_GetArrayViewFromVnlVector(VectorType * vector)
Py_ssize_t len = vector->size();
len *= sizeof(DataType);

const int res = PyBuffer_FillInfo(&pyBuffer, nullptr, vectorBuffer, len, 0, PyBUF_CONTIG);
PyBuffer_FillInfo(&pyBuffer, nullptr, vectorBuffer, len, 0, PyBUF_CONTIG);
PyObject * const memoryView = PyMemoryView_FromBuffer(&pyBuffer);

PyBuffer_Release(&pyBuffer);

return memoryView;
}

Expand All @@ -59,10 +58,12 @@ PyVnl<TElement>::_GetVnlVectorFromArray(PyObject * arr, PyObject * shape) -> con
if (PyObject_GetBuffer(arr, &pyBuffer, PyBUF_CONTIG) == -1)
{
PyErr_SetString(PyExc_RuntimeError, "Cannot get an instance of NumPy array.");
PyBuffer_Release(&pyBuffer);
return VectorType();
}

[[maybe_unused]] const std::unique_ptr<Py_buffer, decltype(&PyBuffer_Release)> bufferScopeGuard(&pyBuffer,
&PyBuffer_Release);

const Py_ssize_t bufferLength = pyBuffer.len;
const void * const buffer = pyBuffer.buf;

Expand All @@ -74,15 +75,13 @@ PyVnl<TElement>::_GetVnlVectorFromArray(PyObject * arr, PyObject * shape) -> con
const size_t numberOfElements = static_cast<size_t>(PyInt_AsLong(item));

const size_t len = numberOfElements * sizeof(DataType);
if (bufferLength != len)
if (bufferLength < 0 || static_cast<size_t>(bufferLength) != len)
{
PyErr_SetString(PyExc_RuntimeError, "Size mismatch of vector and Buffer.");
PyBuffer_Release(&pyBuffer);
return VectorType();
}
const auto * const data = static_cast<const DataType *>(buffer);
VectorType output(data, numberOfElements);
PyBuffer_Release(&pyBuffer);

return output;
}
Expand All @@ -106,11 +105,9 @@ PyVnl<TElement>::_GetArrayViewFromVnlMatrix(MatrixType * matrix)
Py_ssize_t len = matrix->size();
len *= sizeof(DataType);

const int res = PyBuffer_FillInfo(&pyBuffer, nullptr, matrixBuffer, len, 0, PyBUF_CONTIG);
PyBuffer_FillInfo(&pyBuffer, nullptr, matrixBuffer, len, 0, PyBUF_CONTIG);
PyObject * const memoryView = PyMemoryView_FromBuffer(&pyBuffer);

PyBuffer_Release(&pyBuffer);

return memoryView;
}

Expand All @@ -129,10 +126,12 @@ PyVnl<TElement>::_GetVnlMatrixFromArray(PyObject * arr, PyObject * shape) -> con
if (PyObject_GetBuffer(arr, &pyBuffer, PyBUF_CONTIG) == -1)
{
PyErr_SetString(PyExc_RuntimeError, "Cannot get an instance of NumPy array.");
PyBuffer_Release(&pyBuffer);
return MatrixType();
}

[[maybe_unused]] const std::unique_ptr<Py_buffer, decltype(&PyBuffer_Release)> bufferScopeGuard(&pyBuffer,
&PyBuffer_Release);

const Py_ssize_t bufferLength = pyBuffer.len;
const void * const buffer = pyBuffer.buf;

Expand All @@ -148,16 +147,14 @@ PyVnl<TElement>::_GetVnlMatrixFromArray(PyObject * arr, PyObject * shape) -> con
}

const size_t len = numberOfElements * sizeof(DataType);
if (bufferLength != len)
if (bufferLength < 0 || static_cast<size_t>(bufferLength) != len)
{
PyErr_SetString(PyExc_RuntimeError, "Size mismatch of matrix and Buffer.");
PyBuffer_Release(&pyBuffer);
return MatrixType();
}

const auto * const data = static_cast<const DataType *>(buffer);
MatrixType output(data, size[0], size[1]);
PyBuffer_Release(&pyBuffer);

return output;
}
Expand Down

0 comments on commit 89bb76b

Please sign in to comment.