/Wrapping/PythonCore/PyVTKExtras.cxx

https://github.com/CDAT/VTK · C++ · 154 lines · 107 code · 15 blank · 32 comment · 29 complexity · 2c5a1d535dac33dc2dba3ac1215bd905 MD5 · raw file

  1. /*=========================================================================
  2. Program: Visualization Toolkit
  3. Module: PyVTKExtras.cxx
  4. Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  5. All rights reserved.
  6. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  7. This software is distributed WITHOUT ANY WARRANTY; without even
  8. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  9. PURPOSE. See the above copyright notice for more information.
  10. =========================================================================*/
  11. #include "PyVTKExtras.h"
  12. #include "vtkPythonCompatibility.h"
  13. #include "PyVTKMutableObject.h"
  14. // Silence warning like
  15. // "dereferencing type-punned pointer will break strict-aliasing rules"
  16. // it happens because this kind of expression: (long *)&ptr
  17. #if defined(__GNUC__)
  18. #pragma GCC diagnostic ignored "-Wstrict-aliasing"
  19. #endif
  20. //--------------------------------------------------------------------
  21. // Helper function for the buffer_shared() check: get the pointer and
  22. // size (in bytes) of the buffer of the provided object. A return
  23. // value of zero indicates that an exception was raised.
  24. static void *buffer_pointer_and_size(PyObject *o, Py_ssize_t *size)
  25. {
  26. void *ptr = nullptr;
  27. #if PY_VERSION_HEX >= 0x02060000
  28. // New buffer protocol
  29. Py_buffer view = VTK_PYBUFFER_INITIALIZER;
  30. if (PyObject_CheckBuffer(o))
  31. {
  32. // Check for a simple buffer
  33. if (PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) == -1)
  34. {
  35. // Check for a C or Fortran contiguous buffer
  36. PyErr_Clear();
  37. if (PyObject_GetBuffer(o, &view, PyBUF_STRIDES) == -1)
  38. {
  39. return nullptr;
  40. }
  41. }
  42. ptr = view.buf;
  43. *size = view.len;
  44. PyBuffer_Release(&view);
  45. if (ptr)
  46. {
  47. return ptr;
  48. }
  49. }
  50. #endif
  51. #ifndef VTK_PY3K
  52. // Old buffer protocol
  53. PyBufferProcs *b = Py_TYPE(o)->tp_as_buffer;
  54. if (b && b->bf_getreadbuffer && b->bf_getsegcount)
  55. {
  56. if (b->bf_getsegcount(o, nullptr) == 1)
  57. {
  58. *size = b->bf_getreadbuffer(o, 0, &ptr);
  59. if (ptr)
  60. {
  61. return ptr;
  62. }
  63. }
  64. else
  65. {
  66. PyErr_SetString(PyExc_TypeError, "buffer must be single-segment");
  67. return nullptr;
  68. }
  69. }
  70. #endif
  71. PyErr_SetString(PyExc_TypeError,
  72. "object does not have a readable buffer");
  73. return nullptr;
  74. }
  75. //--------------------------------------------------------------------
  76. static PyObject *PyVTKExtras_buffer_shared(PyObject *, PyObject *args)
  77. {
  78. PyObject *ob[2] = { nullptr, nullptr };
  79. if (PyArg_UnpackTuple(args, "buffer_shared", 2, 2, &ob[0], &ob[1]))
  80. {
  81. void *ptr[2] = { nullptr, nullptr };
  82. Py_ssize_t size[2] = { 0, 0 };
  83. for (int i = 0; i < 2; i++)
  84. {
  85. ptr[i] = buffer_pointer_and_size(ob[i], &size[i]);
  86. if (!ptr[i])
  87. {
  88. break;
  89. }
  90. }
  91. // check if the pointers and memory size are equal
  92. if (ptr[0] && ptr[1])
  93. {
  94. if (ptr[0] == ptr[1] && size[0] == size[1])
  95. {
  96. Py_RETURN_TRUE;
  97. }
  98. else
  99. {
  100. Py_RETURN_FALSE;
  101. }
  102. }
  103. }
  104. return nullptr;
  105. }
  106. //--------------------------------------------------------------------
  107. static PyMethodDef PyVTKExtras_Methods[] = {
  108. {"buffer_shared", PyVTKExtras_buffer_shared, METH_VARARGS,
  109. "Check if two objects share the same buffer, meaning that they"
  110. " point to the same block of memory. An TypeError exception will"
  111. " be raised if either of the objects does not provide a buffer."},
  112. {nullptr, nullptr, 0, nullptr}
  113. };
  114. //--------------------------------------------------------------------
  115. // Exported method called by vtkCommonCorePythonInit
  116. void PyVTKAddFile_PyVTKExtras(PyObject *dict)
  117. {
  118. PyObject *o = (PyObject *)&PyVTKMutableObject_Type;
  119. if (o && PyDict_SetItemString(dict, "mutable", o) != 0)
  120. {
  121. Py_DECREF(o);
  122. }
  123. for (PyMethodDef *meth = PyVTKExtras_Methods;
  124. meth->ml_name != nullptr;
  125. meth++)
  126. {
  127. // Third argument would be the module object, but all we have is
  128. // the module's dict, and it's safe to set it to NULL.
  129. o = PyCFunction_NewEx(meth, nullptr, nullptr);
  130. if (o && PyDict_SetItemString(dict, meth->ml_name, o) != 0)
  131. {
  132. Py_DECREF(o);
  133. }
  134. }
  135. }