Commit db9ac320 authored by David Gobbi's avatar David Gobbi Committed by Kitware Robot

Merge topic 'python-py3k-buffer_shared'

8320da24 Add a python function to check buffer equivalence.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Utkarsh Ayachit's avatarUtkarsh Ayachit <utkarsh.ayachit@kitware.com>
Acked-by: Ben Boeckel's avatarBen Boeckel <ben.boeckel@kitware.com>
Merge-request: !512
parents d2586776 8320da24
......@@ -114,5 +114,33 @@ class TestBuffer(Testing.vtkTest):
# test the contents of the memoryview
self.assertEqual(ord(m.tobytes()) & 0xF8, 0x68)
def testBufferShared(self):
"""Test the special buffer_shared() check that VTK provides."""
a = bytearray(b'hello')
self.assertEqual(vtk.buffer_shared(a, a), True)
b = bytearray(b'hello')
self.assertEqual(vtk.buffer_shared(a, b), False)
a = vtk.vtkFloatArray()
a.SetNumberOfComponents(3)
a.InsertNextTuple((10, 7, 4))
a.InsertNextTuple((85, 8, 2))
b = vtk.vtkFloatArray()
b.SetVoidArray(a, 6, True)
self.assertEqual(vtk.buffer_shared(a, b), True)
c = vtk.vtkFloatArray()
c.DeepCopy(a)
self.assertEqual(vtk.buffer_shared(a, c), False)
if sys.hexversion >= 0x02070000:
m = memoryview(a)
self.assertEqual(vtk.buffer_shared(a, m), True)
if sys.hexversion < 0x03000000:
m = buffer(a)
self.assertEqual(vtk.buffer_shared(a, m), True)
if __name__ == "__main__":
Testing.main([(TestBuffer, 'test')])
......@@ -69,6 +69,7 @@ sure that it is installed properly.")
import itertools
import operator
import sys
from vtk import buffer_shared
from vtk.util import numpy_support
from vtk.vtkCommonDataModel import vtkDataObject
import weakref
......@@ -290,11 +291,7 @@ class VTKArray(numpy.ndarray):
try:
# This line tells us that they are referring to the same buffer.
# Much like two pointers referring to same memory location in C/C++.
if sys.hexversion >= 0x03000000:
makebuffer = memoryview
else:
makebuffer = buffer
if makebuffer(slf) == makebuffer(obj2):
if buffer_shared(slf, obj2):
self.VTKObject = getattr(obj, 'VTKObject', None)
except TypeError:
pass
......@@ -304,9 +301,14 @@ class VTKArray(numpy.ndarray):
def __getattr__(self, name):
"Forwards unknown attribute requests to VTK array."
if not hasattr(self, "VTKObject") or not self.VTKObject:
raise AttributeError("class has no attribute %s" % name)
return getattr(self.VTKObject, name)
try:
o = self.__dict__["VTKObject"]
except KeyError:
o = None
if o is None:
raise AttributeError("'%s' object has no attribute '%s'" %
(self.__class__.__name__, name))
return getattr(o, name)
class VTKNoneArrayMetaClass(type):
def __new__(mcs, name, parent, attr):
......
......@@ -7,6 +7,7 @@ set(Module_SRCS
vtkPythonOverload.cxx
vtkPythonUtil.cxx
vtkSmartPyObject.cxx
PyVTKExtras.cxx
PyVTKMethodDescriptor.cxx
PyVTKMutableObject.cxx
PyVTKNamespace.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: PyVTKExtras.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "PyVTKExtras.h"
#include "vtkPythonCompatibility.h"
#include "PyVTKMutableObject.h"
// Silence warning like
// "dereferencing type-punned pointer will break strict-aliasing rules"
// it happens because this kind of expression: (long *)&ptr
// pragma GCC diagnostic is available since gcc>=4.2
#if defined(__GNUC__) && (__GNUC__>4) || (__GNUC__==4 && __GNUC_MINOR__>=2)
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
//--------------------------------------------------------------------
// Helper function for the buffer_shared() check: get the pointer and
// size (in bytes) of the buffer of the provided object. A return
// value of zero indicates that an exception was raised.
static void *buffer_pointer_and_size(PyObject *o, Py_ssize_t *size)
{
void *ptr = NULL;
#if PY_VERSION_HEX >= 0x02060000
// New buffer protocol
Py_buffer view = VTK_PYBUFFER_INITIALIZER;
if (PyObject_CheckBuffer(o))
{
// Check for a simple buffer
if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == -1)
{
// Check for a C or Fortran contiguous buffer
PyErr_Clear();
if (PyObject_GetBuffer(o, &view, PyBUF_STRIDES) == -1)
{
return NULL;
}
}
ptr = view.buf;
*size = view.len;
PyBuffer_Release(&view);
if (ptr)
{
return ptr;
}
}
#endif
#ifndef VTK_PY3K
// Old buffer protocol
PyBufferProcs *b = Py_TYPE(o)->tp_as_buffer;
if (b && b->bf_getreadbuffer && b->bf_getsegcount)
{
if (b->bf_getsegcount(o, NULL) == 1)
{
*size = b->bf_getreadbuffer(o, 0, &ptr);
if (ptr)
{
return ptr;
}
}
else
{
PyErr_SetString(PyExc_TypeError, "buffer must be single-segment");
return NULL;
}
}
#endif
PyErr_SetString(PyExc_TypeError,
"object does not have a readable buffer");
return NULL;
}
//--------------------------------------------------------------------
static PyObject *PyVTKExtras_buffer_shared(PyObject *, PyObject *args)
{
PyObject *ob[2] = { NULL, NULL };
if (PyArg_UnpackTuple(args, "buffer_shared", 2, 2, &ob[0], &ob[1]))
{
void *ptr[2] = { NULL, NULL };
Py_ssize_t size[2] = { 0, 0 };
for (int i = 0; i < 2; i++)
{
ptr[i] = buffer_pointer_and_size(ob[i], &size[i]);
if (!ptr[i])
{
break;
}
}
// check if the pointers and memory size are equal
if (ptr[0] && ptr[1])
{
if (ptr[0] == ptr[1] && size[0] == size[1])
{
Py_RETURN_TRUE;
}
else
{
Py_RETURN_FALSE;
}
}
}
return NULL;
}
//--------------------------------------------------------------------
static PyMethodDef PyVTKExtras_Methods[] = {
{"buffer_shared", PyVTKExtras_buffer_shared, METH_VARARGS,
"Check if two objects share the same buffer, meaning that they"
" point to the same block of memory. An TypeError exception will"
" be raised if either of the objects does not provide a buffer."},
{NULL, NULL, 0, NULL}
};
//--------------------------------------------------------------------
// Exported method called by vtkCommonCorePythonInit
void PyVTKAddFile_PyVTKExtras(PyObject *dict)
{
PyObject *o = (PyObject *)&PyVTKMutableObject_Type;
if (o && PyDict_SetItemString(dict, "mutable", o) != 0)
{
Py_DECREF(o);
}
for (PyMethodDef *meth = PyVTKExtras_Methods;
meth->ml_name != NULL;
meth++)
{
// Third argument would be the module object, but all we have is
// the module's dict, and it's safe to set it to NULL.
o = PyCFunction_NewEx(meth, NULL, NULL);
if (o && PyDict_SetItemString(dict, meth->ml_name, o) != 0)
{
Py_DECREF(o);
}
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: PyVTKExtras.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*-----------------------------------------------------------------------
The PyVTKExtras was created in Aug 2015 by David Gobbi.
This file provides extra classes and functions for the vtk module.
Unlike the contents of vtk.util, the classes and functions provided
here are ones that must be written in C++ instead of pure python.
-----------------------------------------------------------------------*/
#ifndef PyVTKExtras_h
#define PyVTKExtras_h
#include "vtkWrappingPythonCoreModule.h" // For export macro
#include "vtkPython.h"
//--------------------------------------------------------------------
// This will add extras to the provided dict. It is called during the
// initialization of the vtkCommonCore python module.
extern "C"
{
VTKWRAPPINGPYTHONCORE_EXPORT void PyVTKAddFile_PyVTKExtras(PyObject *dict);
}
#endif
......@@ -31,10 +31,6 @@
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
//--------------------------------------------------------------------
// methods for adding this type to a module
extern "C" { VTKWRAPPINGPYTHONCORE_EXPORT void PyVTKAddFile_mutable(PyObject *); }
//--------------------------------------------------------------------
static const char *PyVTKMutableObject_Doc =
......@@ -939,15 +935,3 @@ PyTypeObject PyVTKMutableObject_Type = {
0, // tp_weaklist
VTK_WRAP_PYTHON_SUPPRESS_UNINITIALIZED
};
//--------------------------------------------------------------------
// Exported method for adding this type to a module's dict
void PyVTKAddFile_mutable(PyObject *dict)
{
PyObject *o = (PyObject *)&PyVTKMutableObject_Type;
if (o && PyDict_SetItemString(dict, "mutable", o) != 0)
{
Py_DECREF(o);
}
}
......@@ -168,11 +168,10 @@ int main(int argc,char *argv[])
return 1;
}
/* extra object for the Common module */
/* extra functions, types, etc. for the CommonCore module */
if (strcmp(libName, "vtkCommonCorePython") == 0)
{
/* the PyVTKMutableObject */
files[numFiles] = strdup("mutable");
files[numFiles] = strdup("PyVTKExtras");
numFiles++;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment