/*========================================================================= Program: Visualization Toolkit Module: vtkPythonArgs.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. =========================================================================*/ /*----------------------------------------------------------------------- The vtkPythonArgs class was created in Oct 2010 by David Gobbi. This class provides methods for reading an argument tuple from Python and converting it to types that can be used by VTK. It is meant to be more efficient and flexible that the original PyArg_ParseTuple() code, resulting in wrapper code that is faster and more compact. -----------------------------------------------------------------------*/ // Keep vtkPythonArgs.h from declaring externs for templates we instantiate #define vtkPythonArgs_cxx #include "vtkPythonArgs.h" #include "vtkPythonUtil.h" #include "vtkObjectBase.h" //-------------------------------------------------------------------- // Extract various C++ types from python objects. The rules are // identical to PyArg_ParseTuple except that range checking is done // on unsigned values. // Macro to mimic a check done in PyArg_ParseTuple #define VTK_PYTHON_FLOAT_CHECK()\ if (PyFloat_Check(o)) \ { \ PyErr_SetString(PyExc_TypeError, \ "integer argument expected, got float"); \ return false; \ } inline bool vtkPythonGetValue(PyObject *o, long &a) { VTK_PYTHON_FLOAT_CHECK(); a = PyInt_AsLong(o); return (a != static_cast(-1) || !PyErr_Occurred()); } inline bool vtkPythonGetValue(PyObject *o, unsigned long &a) { VTK_PYTHON_FLOAT_CHECK(); a = PyLong_AsUnsignedLong(o); return (a != static_cast(-1) || !PyErr_Occurred()); } template inline bool vtkPythonGetLongLongValue(PyObject *o, T &a) { VTK_PYTHON_FLOAT_CHECK(); PY_LONG_LONG i = PyLong_AsLongLong(o); a = static_cast(i); return (i != static_cast(-1) || !PyErr_Occurred()); } template inline bool vtkPythonGetUnsignedLongLongValue(PyObject *o, T &a) { VTK_PYTHON_FLOAT_CHECK(); // PyLong_AsUnsignedLongLong will fail if "o" is not a PyLong if (PyLong_Check(o)) { unsigned PY_LONG_LONG i = PyLong_AsUnsignedLongLong(o); a = static_cast(i); return (i != static_cast(-1) || !PyErr_Occurred()); } unsigned long l = PyLong_AsUnsignedLong(o); a = static_cast(l); return (l != static_cast(-1) || !PyErr_Occurred()); } template inline bool vtkPythonGetStringValue(PyObject *o, T *&a, const char *exctext) { if (PyBytes_Check(o)) { #if PY_VERSION_HEX >= 0x03070000 a = const_cast(PyBytes_AS_STRING(o)); return true; #else a = PyBytes_AS_STRING(o); return true; #endif } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(o)) { #if PY_VERSION_HEX >= 0x03070000 a = const_cast(PyUnicode_AsUTF8(o)); return true; #elif PY_VERSION_HEX >= 0x03030000 a = PyUnicode_AsUTF8(o); return true; #else PyObject *s = _PyUnicode_AsDefaultEncodedString(o, nullptr); if (s) { a = PyBytes_AS_STRING(s); return true; } exctext = "(unicode conversion error)"; #endif } #endif PyErr_SetString(PyExc_TypeError, exctext); return false; } inline bool vtkPythonGetStdStringValue(PyObject *o, std::string &a, const char *exctext) { if (PyBytes_Check(o)) { char* val; Py_ssize_t len; PyBytes_AsStringAndSize(o, &val, &len); a = std::string(val, len); return true; } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(o)) { #if PY_VERSION_HEX >= 0x03030000 Py_ssize_t len; const char* val = PyUnicode_AsUTF8AndSize(o, &len); a = std::string(val, len); return true; #else PyObject *s = _PyUnicode_AsDefaultEncodedString(o, nullptr); if (s) { char* val; Py_ssize_t len; PyBytes_AsStringAndSize(s, &val, &len); a = std::string(val, len); return true; } exctext = "(unicode conversion error)"; #endif } #endif PyErr_SetString(PyExc_TypeError, exctext); return false; } //-------------------------------------------------------------------- // Overloaded methods, mostly based on the above templates // Get a void pointer to the contents of a buffer of type "btype", where // btype one of the type characters defined in the python "struct" module. static bool vtkPythonGetValue( PyObject *o, const void *&a, Py_buffer *view, char btype) { void *p = nullptr; Py_ssize_t sz = 0; const char *format = nullptr; #ifndef VTK_PY3K PyBufferProcs *b = Py_TYPE(o)->tp_as_buffer; #endif #if PY_VERSION_HEX < 0x02060000 (void)view; #else #ifdef VTK_PY3K PyObject *bytes = nullptr; if (PyUnicode_Check(o)) { bytes = PyUnicode_AsUTF8String(o); PyBytes_AsStringAndSize(bytes, reinterpret_cast(&p), &sz); } else #endif if (PyObject_CheckBuffer(o)) { int flags = (PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT); if (btype == '\0') { // if btype indicates "void *", use simple buffer flags = PyBUF_SIMPLE; } // use the modern python buffer interface if (PyObject_GetBuffer(o, view, flags) == -1) { return false; } p = view->buf; sz = view->len; format = view->format; // check to see if the type is compatible if (btype != '\0') { // if "btype" is set, then check type compatibility char vtype = (format ? format[0] : 'B'); if (vtype == '@') { vtype = format[1]; } if (btype != vtype) { PyErr_Format(PyExc_TypeError, "incorrect buffer type, expected %c but received %s", btype, (format ? format : "B")); return false; } } } #ifndef VTK_PY3K else #endif #endif #ifndef VTK_PY3K // use the old buffer interface if (b && b->bf_getreadbuffer && b->bf_getsegcount) { if (b->bf_getsegcount(o, nullptr) == 1) { sz = b->bf_getreadbuffer(o, 0, &p); } else { PyErr_SetString(PyExc_TypeError, "buffer must be single-segment"); return false; } } #endif #ifdef VTK_PY3K if (bytes && btype == '\0') #else if (p && sz >= 0 && sz <= VTK_INT_MAX && btype == '\0' && (format == nullptr || format[0] == 'c' || format[0] == 'B')) #endif { // check for pointer mangled as string int s = static_cast(sz); a = vtkPythonUtil::UnmanglePointer( reinterpret_cast(p), &s, "p_void"); #ifdef VTK_PY3K Py_DECREF(bytes); if (s != 0) { PyErr_SetString(PyExc_TypeError, "requires a _addr_p_void string"); return false; } #else if (s == -1) { // matched _addr_ but not p_void, assume it isn't a swig ptr string: // use the buffer's pointer as the argument a = p; } #endif return true; } else if (p && sz >= 0) { // directly use the pointer to the buffer contents a = p; return true; } PyErr_SetString(PyExc_TypeError, "object does not have a readable buffer"); return false; } inline bool vtkPythonGetValue( PyObject *o, void *&a, Py_buffer *buf, char btype) { // should have an alternate form for non-const "void *" that uses // writebuffer instead of readbuffer, but that would break existing code const void *b = nullptr; bool r = vtkPythonGetValue(o, b, buf, btype); a = const_cast(b); return r; } inline bool vtkPythonGetValue(PyObject *o, const char *&a) { a = nullptr; return (o == Py_None || vtkPythonGetStringValue(o, a, "string or None required")); } inline bool vtkPythonGetValue(PyObject *o, char *&a) { a = nullptr; return (o == Py_None || vtkPythonGetStringValue(o, a, "string or None required")); } inline bool vtkPythonGetValue(PyObject *o, std::string &a) { if (vtkPythonGetStdStringValue(o, a, "string is required")) { return true; } return false; } inline bool vtkPythonGetValue(PyObject *o, vtkUnicodeString &a) { #ifdef Py_USING_UNICODE PyObject *s = PyUnicode_AsUTF8String(o); if (s) { a = vtkUnicodeString::from_utf8(PyBytes_AS_STRING(s)); Py_DECREF(s); return true; } return false; #else a.clear(); PyErr_SetString(PyExc_TypeError, "python built without unicode support"); return false; #endif } inline bool vtkPythonGetValue(PyObject *o, char &a) { static const char exctext[] = "a string of length 1 is required"; const char *b; if (vtkPythonGetStringValue(o, b, exctext)) { if (b[0] == '\0' || b[1] == '\0') { a = b[0]; return true; } PyErr_SetString(PyExc_TypeError, exctext); } return false; } inline bool vtkPythonGetValue(PyObject *o, bool &a) { int i = PyObject_IsTrue(o); a = (i != 0); return (i != -1); } inline bool vtkPythonGetValue(PyObject *o, float &a) { a = static_cast(PyFloat_AsDouble(o)); return (a != -1.0f || !PyErr_Occurred()); } inline bool vtkPythonGetValue(PyObject *o, double &a) { a = PyFloat_AsDouble(o); return (a != -1.0f || !PyErr_Occurred()); } inline bool vtkPythonGetValue(PyObject *o, signed char &a) { long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); if (i >= VTK_SIGNED_CHAR_MIN && i <= VTK_SIGNED_CHAR_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for signed char"); } return false; } inline bool vtkPythonGetValue(PyObject *o, unsigned char &a) { long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); if (i >= VTK_UNSIGNED_CHAR_MIN && i <= VTK_UNSIGNED_CHAR_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for unsigned char"); } return false; } inline bool vtkPythonGetValue(PyObject *o, short &a) { long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); if (i >= VTK_SHORT_MIN && i <= VTK_SHORT_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for short"); } return false; } inline bool vtkPythonGetValue(PyObject *o, unsigned short &a) { long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); if (i >= VTK_UNSIGNED_SHORT_MIN && i <= VTK_UNSIGNED_SHORT_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for unsigned short"); } return false; } inline bool vtkPythonGetValue(PyObject *o, int &a) { long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); #if VTK_SIZEOF_INT < VTK_SIZEOF_LONG if (i >= VTK_INT_MIN && i <= VTK_INT_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for int"); #else return true; #endif } return false; } inline bool vtkPythonGetValue(PyObject *o, unsigned int &a) { #if VTK_SIZEOF_INT < VTK_SIZEOF_LONG long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); if (i >= VTK_UNSIGNED_INT_MIN && i <= VTK_UNSIGNED_INT_MAX) { return true; } PyErr_SetString(PyExc_OverflowError, "value is out of range for unsigned int"); } return false; #else unsigned long i = 0; if (vtkPythonGetValue(o, i)) { a = static_cast(i); return true; } return false; #endif } inline bool vtkPythonGetValue(PyObject *o, long long &a) { return vtkPythonGetLongLongValue(o, a); } inline bool vtkPythonGetValue(PyObject *o, unsigned long long &a) { return vtkPythonGetUnsignedLongLongValue(o, a); } //-------------------------------------------------------------------- // Method for setting a C++ array from a Python sequence. static bool vtkPythonSequenceError(PyObject *o, Py_ssize_t n, Py_ssize_t m); template inline bool vtkPythonGetArray(PyObject *o, T *a, int n) { if (a) { Py_ssize_t m = n; if (PyTuple_Check(o)) { m = PyTuple_GET_SIZE(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { PyObject *s = PyTuple_GET_ITEM(o, i); r = vtkPythonGetValue(s, a[i]); } return r; } } else if (PyList_Check(o)) { m = PyList_GET_SIZE(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { PyObject *s = PyList_GET_ITEM(o, i); r = vtkPythonGetValue(s, a[i]); } return r; } } else if (PySequence_Check(o)) { m = PySequence_Size(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { r = false; PyObject *s = PySequence_GetItem(o, i); if (s && vtkPythonGetValue(s, a[i])) { Py_DECREF(s); r = true; } } return r; } } return vtkPythonSequenceError(o, n, m); } return true; } //-------------------------------------------------------------------- // Method for setting an n-dimensional C++ arrays from a Python sequence. template bool vtkPythonGetNArray(PyObject *o, T *a, int ndim, const int *dims) { if (a) { int inc = 1; for (int j = 1; j < ndim; j++) { inc *= dims[j]; } int n = dims[0]; Py_ssize_t m = n; if (PyList_Check(o)) { m = PyList_GET_SIZE(o); if (m == n) { bool r = true; if (ndim > 1) { for (int i = 0; i < n && r; i++) { PyObject *s = PyList_GET_ITEM(o, i); r = vtkPythonGetNArray(s, a, ndim-1, dims+1); a += inc; } } else { for (int i = 0; i < n && r; i++) { PyObject *s = PyList_GET_ITEM(o, i); r = vtkPythonGetValue(s, a[i]); } } return r; } } else if (PySequence_Check(o)) { m = PySequence_Size(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { r = false; PyObject *s = PySequence_GetItem(o, i); if (s) { if (ndim > 1) { r = vtkPythonGetNArray(s, a, ndim-1, dims+1); a += inc; } else { r = vtkPythonGetValue(s, a[i]); } Py_DECREF(s); } } return r; } } return vtkPythonSequenceError(o, n, m); } return true; } //-------------------------------------------------------------------- // Method for setting a python sequence from a C++ array template inline bool vtkPythonSetArray(PyObject *o, const T *a, int n) { if (a) { Py_ssize_t m = n; if (PyList_Check(o)) { m = PyList_GET_SIZE(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { r = false; PyObject *s = vtkPythonArgs::BuildValue(a[i]); if (s) { Py_DECREF(PyList_GET_ITEM(o, i)); PyList_SET_ITEM(o, i, s); r = true; } } return r; } } else if (PySequence_Check(o)) { m = PySequence_Size(o); if (m == n) { bool r = true; for (int i = 0; i < n && r; i++) { r = false; PyObject *s = vtkPythonArgs::BuildValue(a[i]); if (s) { r = (PySequence_SetItem(o, i, s) != -1); Py_DECREF(s); } } return r; } } return vtkPythonSequenceError(o, n, m); } return true; } //-------------------------------------------------------------------- // Method for setting a python array from an n-dimensional C++ array template bool vtkPythonSetNArray( PyObject *o, const T *a, int ndim, const int *dims) { if (a) { int inc = 1; for (int j = 1; j < ndim; j++) { inc *= dims[j]; } int n = dims[0]; Py_ssize_t m = n; if (PyList_Check(o)) { m = PyList_GET_SIZE(o); if (m == n) { bool r = true; if (ndim > 1) { for (int i = 0; i < n && r; i++) { PyObject *s = PyList_GET_ITEM(o, i); r = vtkPythonSetNArray(s, a, ndim-1, dims+1); a += inc; } } else { for (int i = 0; i < n && r; i++) { r = false; PyObject *s = vtkPythonArgs::BuildValue(a[i]); if (s) { Py_DECREF(PyList_GET_ITEM(o, i)); PyList_SET_ITEM(o, i, s); r = true; } } } return r; } } else if (PySequence_Check(o)) { m = PySequence_Size(o); if (m == n) { bool r = true; if (ndim > 1) { for (int i = 0; i < n && r; i++) { r = false; PyObject *s = PySequence_GetItem(o, i); if (s) { r = vtkPythonSetNArray(s, a, ndim-1, dims+1); a += inc; Py_DECREF(s); } } } else { for (int i = 0; i < n && r; i++) { r = false; PyObject *s = vtkPythonArgs::BuildValue(a[i]); if (s) { r = (PySequence_SetItem(o, i, s) != -1); Py_DECREF(s); } } } return r; } } return vtkPythonSequenceError(o, n, m); } return true; } //-------------------------------------------------------------------- // Define all the "BuildValue" array methods defined in the class. template inline PyObject *vtkPythonBuildTuple(const T *a, int n) { if (a) { PyObject *t = PyTuple_New(n); for (int i = 0; i < n; i++) { PyObject *o = vtkPythonArgs::BuildValue(a[i]); PyTuple_SET_ITEM(t, i, o); } return t; } Py_INCREF(Py_None); return Py_None; } #define VTK_PYTHON_BUILD_TUPLE(T) \ PyObject *vtkPythonArgs::BuildTuple(const T *a, int n) \ { \ return vtkPythonBuildTuple(a, n); \ } VTK_PYTHON_BUILD_TUPLE(bool) VTK_PYTHON_BUILD_TUPLE(float) VTK_PYTHON_BUILD_TUPLE(double) VTK_PYTHON_BUILD_TUPLE(signed char) VTK_PYTHON_BUILD_TUPLE(unsigned char) VTK_PYTHON_BUILD_TUPLE(short) VTK_PYTHON_BUILD_TUPLE(unsigned short) VTK_PYTHON_BUILD_TUPLE(int) VTK_PYTHON_BUILD_TUPLE(unsigned int) VTK_PYTHON_BUILD_TUPLE(long) VTK_PYTHON_BUILD_TUPLE(unsigned long) VTK_PYTHON_BUILD_TUPLE(long long) VTK_PYTHON_BUILD_TUPLE(unsigned long long) //-------------------------------------------------------------------- // If "self" is a class, get real "self" from arg list PyObject *vtkPythonArgs::GetSelfFromFirstArg( PyObject *self, PyObject *args) { if (PyType_Check(self)) { PyTypeObject *pytype = (PyTypeObject *)self; if (PyTuple_GET_SIZE(args) > 0) { self = PyTuple_GET_ITEM(args, 0); if (PyObject_TypeCheck(self, pytype)) { return self; } } char buf[256]; snprintf(buf, sizeof(buf), "unbound method requires a %.200s as the first argument", pytype->tp_name); PyErr_SetString(PyExc_TypeError, buf); return nullptr; } PyErr_SetString(PyExc_TypeError, "unbound method requires a vtkobject"); return nullptr; } //-------------------------------------------------------------------- // Define the GetArg methods for getting objects PyObject *vtkPythonArgs::GetArgAsPythonObject( bool &valid) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); valid = true; return o; } PyObject *vtkPythonArgs::GetArgAsPythonObject( PyObject *o, bool &valid) { valid = true; return o; } vtkObjectBase *vtkPythonArgs::GetArgAsVTKObject( const char *classname, bool &valid) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); vtkObjectBase *r = vtkPythonArgs::GetArgAsVTKObject(o, classname, valid); if (!valid) { this->RefineArgTypeError(this->I - this->M - 1); } return r; } vtkObjectBase *vtkPythonArgs::GetArgAsVTKObject( PyObject *o, const char *classname, bool &valid) { vtkObjectBase *r = vtkPythonUtil::GetPointerFromObject(o, classname); valid = (r || o == Py_None); return r; } void *vtkPythonArgs::GetArgAsSpecialObject( const char *classname, PyObject **p) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); void *r = vtkPythonArgs::GetArgAsSpecialObject(o, classname, p); if (r == nullptr) { this->RefineArgTypeError(this->I - this->M - 1); } return r; } void *vtkPythonArgs::GetArgAsSpecialObject( PyObject *o, const char *classname, PyObject **p) { void *r = vtkPythonUtil::GetPointerFromSpecialObject(o, classname, p); return r; } int vtkPythonArgs::GetArgAsEnum(const char *enumname, bool &valid) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); int i = vtkPythonArgs::GetArgAsEnum(o, enumname, valid); if (!valid) { this->RefineArgTypeError(this->I - this->M - 1); } return i; } int vtkPythonArgs::GetArgAsEnum( PyObject *o, const char *enumname, bool &valid) { long i = 0; PyTypeObject *pytype = vtkPythonUtil::FindEnum(enumname); if (pytype && PyObject_TypeCheck(o, pytype)) { i = PyInt_AsLong(o); valid = true; } else { std::string errstring = "expected enum "; errstring += enumname; errstring += ", got "; errstring += Py_TYPE(o)->tp_name; PyErr_SetString(PyExc_TypeError, errstring.c_str()); valid = false; } return i; } //-------------------------------------------------------------------- // Define the methods for SIP objects void *vtkPythonArgs::GetArgAsSIPObject(const char *classname, bool &valid) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); void *r = vtkPythonArgs::GetArgAsSIPObject(o, classname, valid); if (!valid) { this->RefineArgTypeError(this->I - this->M - 1); } return r; } void *vtkPythonArgs::GetArgAsSIPObject( PyObject *o, const char *classname, bool &valid) { void *r = vtkPythonUtil::SIPGetPointerFromObject(o, classname); valid = (r || !PyErr_Occurred()); return (valid ? r : nullptr); } int vtkPythonArgs::GetArgAsSIPEnum(const char *classname, bool &valid) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); int i = vtkPythonArgs::GetArgAsSIPEnum(o, classname, valid); if (!valid) { this->RefineArgTypeError(this->I - this->M - 1); } return i; } int vtkPythonArgs::GetArgAsSIPEnum( PyObject *o, const char *classname, bool &valid) { int i = 0; valid = (vtkPythonUtil::SIPGetPointerFromObject(o, classname) && vtkPythonGetValue(o, i)); return (valid ? i : 0); } //-------------------------------------------------------------------- // Define all the "GetValue" methods in the class. #define VTK_PYTHON_GET_ARG(T) \ bool vtkPythonArgs::GetValue(T &a) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); \ if (PyVTKReference_Check(o)) \ { \ o = PyVTKReference_GetValue(o); \ } \ if (vtkPythonGetValue(o, a)) \ { \ return true; \ } \ this->RefineArgTypeError(this->I - this->M - 1); \ return false; \ } \ \ bool vtkPythonArgs::GetValue(PyObject *o, T &a) \ { \ return vtkPythonGetValue(o, a); \ } VTK_PYTHON_GET_ARG(char *) VTK_PYTHON_GET_ARG(const char *) VTK_PYTHON_GET_ARG(std::string) VTK_PYTHON_GET_ARG(vtkUnicodeString) VTK_PYTHON_GET_ARG(char) VTK_PYTHON_GET_ARG(bool) VTK_PYTHON_GET_ARG(float) VTK_PYTHON_GET_ARG(double) VTK_PYTHON_GET_ARG(signed char) VTK_PYTHON_GET_ARG(unsigned char) VTK_PYTHON_GET_ARG(short) VTK_PYTHON_GET_ARG(unsigned short) VTK_PYTHON_GET_ARG(int) VTK_PYTHON_GET_ARG(unsigned int) VTK_PYTHON_GET_ARG(long) VTK_PYTHON_GET_ARG(unsigned long) VTK_PYTHON_GET_ARG(long long) VTK_PYTHON_GET_ARG(unsigned long long) //-------------------------------------------------------------------- // Define all the GetArray methods in the class. #define VTK_PYTHON_GET_ARRAY_ARG(T) \ bool vtkPythonArgs::GetArray(T *a, int n) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); \ if (vtkPythonGetArray(o, a, n)) \ { \ return true; \ } \ this->RefineArgTypeError(this->I - this->M - 1); \ return false; \ } VTK_PYTHON_GET_ARRAY_ARG(bool) VTK_PYTHON_GET_ARRAY_ARG(float) VTK_PYTHON_GET_ARRAY_ARG(double) VTK_PYTHON_GET_ARRAY_ARG(char) VTK_PYTHON_GET_ARRAY_ARG(signed char) VTK_PYTHON_GET_ARRAY_ARG(unsigned char) VTK_PYTHON_GET_ARRAY_ARG(short) VTK_PYTHON_GET_ARRAY_ARG(unsigned short) VTK_PYTHON_GET_ARRAY_ARG(int) VTK_PYTHON_GET_ARRAY_ARG(unsigned int) VTK_PYTHON_GET_ARRAY_ARG(long) VTK_PYTHON_GET_ARRAY_ARG(unsigned long) VTK_PYTHON_GET_ARRAY_ARG(long long) VTK_PYTHON_GET_ARRAY_ARG(unsigned long long) //-------------------------------------------------------------------- // Define all the GetNArray methods in the class. #define VTK_PYTHON_GET_NARRAY_ARG(T) \ bool vtkPythonArgs::GetNArray(T *a, int ndim, const int *dims) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); \ if (vtkPythonGetNArray(o, a, ndim, dims)) \ { \ return true; \ } \ this->RefineArgTypeError(this->I - this->M - 1); \ return false; \ } VTK_PYTHON_GET_NARRAY_ARG(bool) VTK_PYTHON_GET_NARRAY_ARG(float) VTK_PYTHON_GET_NARRAY_ARG(double) VTK_PYTHON_GET_NARRAY_ARG(char) VTK_PYTHON_GET_NARRAY_ARG(signed char) VTK_PYTHON_GET_NARRAY_ARG(unsigned char) VTK_PYTHON_GET_NARRAY_ARG(short) VTK_PYTHON_GET_NARRAY_ARG(unsigned short) VTK_PYTHON_GET_NARRAY_ARG(int) VTK_PYTHON_GET_NARRAY_ARG(unsigned int) VTK_PYTHON_GET_NARRAY_ARG(long) VTK_PYTHON_GET_NARRAY_ARG(unsigned long) VTK_PYTHON_GET_NARRAY_ARG(long long) VTK_PYTHON_GET_NARRAY_ARG(unsigned long long) //-------------------------------------------------------------------- // Define the special function pointer GetValue method bool vtkPythonArgs::GetFunction(PyObject *arg, PyObject *&o) { o = arg; if (o == Py_None || PyCallable_Check(o)) { return true; } PyErr_SetString(PyExc_TypeError, "a callable object is required"); return false; } bool vtkPythonArgs::GetFunction(PyObject *&o) { PyObject *arg = PyTuple_GET_ITEM(this->Args, this->I++); return vtkPythonArgs::GetFunction(arg, o); } //-------------------------------------------------------------------- // Define the void pointer GetValue method #define VTK_PYTHON_GET_BUFFER(T, btype) \ bool vtkPythonArgs::GetBuffer(T* &a, Py_buffer *buf) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); \ void *v; \ if (vtkPythonGetValue(o, v, buf, btype)) \ { \ a = static_cast(v); \ return true; \ } \ this->RefineArgTypeError(this->I - this->M - 1); \ return false; \ } \ \ bool vtkPythonArgs::GetBuffer(const T* &a, Py_buffer *buf) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->I++); \ const void *v; \ if (vtkPythonGetValue(o, v, buf, btype)) \ { \ a = static_cast(v); \ return true; \ } \ this->RefineArgTypeError(this->I - this->M - 1); \ return false; \ } \ \ bool vtkPythonArgs::GetBuffer(PyObject *o, T* &a, Py_buffer *buf) \ { \ void *v; \ if (vtkPythonGetValue(o, v, buf, btype)) \ { \ a = static_cast(v); \ return true; \ } \ return false; \ } \ \ bool vtkPythonArgs::GetBuffer(PyObject *o, const T* &a, Py_buffer *buf) \ { \ const void *v; \ if (vtkPythonGetValue(o, v, buf, btype)) \ { \ a = static_cast(v); \ return true; \ } \ return false; \ } VTK_PYTHON_GET_BUFFER(void, '\0') VTK_PYTHON_GET_BUFFER(float, 'f') VTK_PYTHON_GET_BUFFER(double, 'd') VTK_PYTHON_GET_BUFFER(bool, '\?') VTK_PYTHON_GET_BUFFER(char, 'c') VTK_PYTHON_GET_BUFFER(signed char, 'b') VTK_PYTHON_GET_BUFFER(unsigned char, 'B') VTK_PYTHON_GET_BUFFER(short, 'h') VTK_PYTHON_GET_BUFFER(unsigned short, 'H') VTK_PYTHON_GET_BUFFER(int, 'i') VTK_PYTHON_GET_BUFFER(unsigned int, 'I') VTK_PYTHON_GET_BUFFER(long, 'l') VTK_PYTHON_GET_BUFFER(unsigned long, 'L') VTK_PYTHON_GET_BUFFER(long long, 'q') VTK_PYTHON_GET_BUFFER(unsigned long long, 'Q') //-------------------------------------------------------------------- // Define all the SetArgValue methods for setting reference args #define VTK_PYTHON_SET_ARG(T) \ bool vtkPythonArgs::SetArgValue(int i, T a) \ { \ if (this->M + i < this->N) \ { \ PyObject *m = PyTuple_GET_ITEM(this->Args, this->M + i); \ PyObject *o = vtkPythonArgs::BuildValue(a); \ int r = PyVTKReference_SetValue(m, o); \ if (r == 0) \ { \ return true; \ } \ this->RefineArgTypeError(i); \ return false; \ } \ return true; \ } #define VTK_PYTHON_SET_ARGN(T) \ bool vtkPythonArgs::SetArgValue(int i, const T *a, int n) \ { \ if (this->M + i < this->N) \ { \ PyObject *m = PyTuple_GET_ITEM(this->Args, this->M + i); \ PyObject *o = vtkPythonArgs::BuildTuple(a, n); \ int r = PyVTKReference_SetValue(m, o); \ if (r == 0) \ { \ return true; \ } \ this->RefineArgTypeError(i); \ return false; \ } \ return true; \ } VTK_PYTHON_SET_ARG(const std::string &) VTK_PYTHON_SET_ARG(const vtkUnicodeString &) VTK_PYTHON_SET_ARG(char) VTK_PYTHON_SET_ARG(bool) VTK_PYTHON_SET_ARG(float) VTK_PYTHON_SET_ARG(double) VTK_PYTHON_SET_ARG(signed char) VTK_PYTHON_SET_ARG(unsigned char) VTK_PYTHON_SET_ARG(short) VTK_PYTHON_SET_ARG(unsigned short) VTK_PYTHON_SET_ARG(int) VTK_PYTHON_SET_ARG(unsigned int) VTK_PYTHON_SET_ARG(long) VTK_PYTHON_SET_ARG(unsigned long) VTK_PYTHON_SET_ARG(long long) VTK_PYTHON_SET_ARG(unsigned long long) VTK_PYTHON_SET_ARGN(bool) VTK_PYTHON_SET_ARGN(float) VTK_PYTHON_SET_ARGN(double) VTK_PYTHON_SET_ARGN(signed char) VTK_PYTHON_SET_ARGN(unsigned char) VTK_PYTHON_SET_ARGN(short) VTK_PYTHON_SET_ARGN(unsigned short) VTK_PYTHON_SET_ARGN(int) VTK_PYTHON_SET_ARGN(unsigned int) VTK_PYTHON_SET_ARGN(long) VTK_PYTHON_SET_ARGN(unsigned long) VTK_PYTHON_SET_ARGN(long long) VTK_PYTHON_SET_ARGN(unsigned long long) //-------------------------------------------------------------------- // Define all the SetArgValue methods for setting array args #define VTK_PYTHON_SET_ARRAY_ARG(T) \ bool vtkPythonArgs::SetArray(int i, const T *a, int n) \ { \ if (this->M + i < this->N) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->M + i); \ if (vtkPythonSetArray(o, a, n)) \ { \ return true; \ } \ this->RefineArgTypeError(i); \ return false; \ } \ return true; \ } VTK_PYTHON_SET_ARRAY_ARG(bool) VTK_PYTHON_SET_ARRAY_ARG(float) VTK_PYTHON_SET_ARRAY_ARG(double) VTK_PYTHON_SET_ARRAY_ARG(char) VTK_PYTHON_SET_ARRAY_ARG(signed char) VTK_PYTHON_SET_ARRAY_ARG(unsigned char) VTK_PYTHON_SET_ARRAY_ARG(short) VTK_PYTHON_SET_ARRAY_ARG(unsigned short) VTK_PYTHON_SET_ARRAY_ARG(int) VTK_PYTHON_SET_ARRAY_ARG(unsigned int) VTK_PYTHON_SET_ARRAY_ARG(long) VTK_PYTHON_SET_ARRAY_ARG(unsigned long) VTK_PYTHON_SET_ARRAY_ARG(long long) VTK_PYTHON_SET_ARRAY_ARG(unsigned long long) //-------------------------------------------------------------------- // Define all the SetArgValue methods for setting multi-dim array args #define VTK_PYTHON_SET_NARRAY_ARG(T) \ bool vtkPythonArgs::SetNArray( \ int i, const T *a, int ndim, const int *dims) \ { \ if (this->M + i < this->N) \ { \ PyObject *o = PyTuple_GET_ITEM(this->Args, this->M + i); \ if (vtkPythonSetNArray(o, a, ndim, dims)) \ { \ return true; \ } \ this->RefineArgTypeError(i); \ return false; \ } \ return true; \ } VTK_PYTHON_SET_NARRAY_ARG(bool) VTK_PYTHON_SET_NARRAY_ARG(float) VTK_PYTHON_SET_NARRAY_ARG(double) VTK_PYTHON_SET_NARRAY_ARG(char) VTK_PYTHON_SET_NARRAY_ARG(signed char) VTK_PYTHON_SET_NARRAY_ARG(unsigned char) VTK_PYTHON_SET_NARRAY_ARG(short) VTK_PYTHON_SET_NARRAY_ARG(unsigned short) VTK_PYTHON_SET_NARRAY_ARG(int) VTK_PYTHON_SET_NARRAY_ARG(unsigned int) VTK_PYTHON_SET_NARRAY_ARG(long) VTK_PYTHON_SET_NARRAY_ARG(unsigned long) VTK_PYTHON_SET_NARRAY_ARG(long long) VTK_PYTHON_SET_NARRAY_ARG(unsigned long long) //-------------------------------------------------------------------- // Raise an exception about incorrect arg count. bool vtkPythonArgs::ArgCountError(int m, int n) { char text[256]; const char *name = this->MethodName; int nargs = this->N; snprintf(text, sizeof(text), "%.200s%s takes %s %d argument%s (%d given)", (name ? name : "function"), (name ? "()" : ""), ((m == n) ? "exactly" : ((nargs < m) ? "at least" : "at most")), ((nargs < m) ? m : n), ((((nargs < m) ? m : n)) == 1 ? "" : "s"), nargs); PyErr_SetString(PyExc_TypeError, text); return false; } //-------------------------------------------------------------------- // Static method to write an arg count error. bool vtkPythonArgs::ArgCountError(int n, const char *name) { char text[256]; snprintf(text, sizeof(text), "no overloads of %.200s%s take %d argument%s", (name ? name : "function"), (name ? "()" : ""), n, (n == 1 ? "" : "s")); PyErr_SetString(PyExc_TypeError, text); return false; } //-------------------------------------------------------------------- // Static method to raise an exception on a failed precondition. bool vtkPythonArgs::PrecondError(const char *ctext) { char text[256]; snprintf(text, sizeof(text), "expects %.200s", ctext); PyErr_SetString(PyExc_ValueError, text); return false; } //-------------------------------------------------------------------- // Raise an exception about pure virtual method call bool vtkPythonArgs::PureVirtualError() { char text[256]; snprintf(text, sizeof(text), "pure virtual method %.200s() was called", this->MethodName); PyErr_SetString(PyExc_TypeError, text); return false; } //-------------------------------------------------------------------- // Refine an error by saying what argument it is for bool vtkPythonArgs::RefineArgTypeError(int i) { if (PyErr_ExceptionMatches(PyExc_TypeError) || PyErr_ExceptionMatches(PyExc_ValueError) || PyErr_ExceptionMatches(PyExc_OverflowError)) { PyObject *exc; PyObject *val, *newval; PyObject *frame; PyErr_Fetch(&exc, &val, &frame); #ifdef VTK_PY3K const char *cp = ""; if (val && !PyUnicode_Check(val)) { Py_DECREF(val); val = 0; } newval = PyUnicode_FromFormat("%s argument %d: %V", this->MethodName, i+1, val, cp); #else const char *cp = ""; if (val && PyString_Check(val)) { cp = PyString_AsString(val); } newval = PyString_FromFormat("%s argument %d: %s", this->MethodName, i+1, cp); #endif Py_XDECREF(val); PyErr_Restore(exc, newval, frame); } return false; } //-------------------------------------------------------------------- // Raise a type error for a sequence arg of wrong type or size. bool vtkPythonSequenceError(PyObject *o, Py_ssize_t n, Py_ssize_t m) { char text[80]; if (m == n) { snprintf(text, sizeof(text), "expected a sequence of %ld value%s, got %s", (long)n, ((n == 1) ? "" : "s"), Py_TYPE(o)->tp_name); } else { snprintf(text, sizeof(text), "expected a sequence of %ld value%s, got %ld values", (long)n, ((n == 1) ? "" : "s"), (long)m); } PyErr_SetString(PyExc_TypeError, text); return false; } //-------------------------------------------------------------------- // Checking size of array arg. int vtkPythonArgs::GetArgSize(int i) { int size = 0; if (this->M + i < this->N) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->M + i); if (PySequence_Check(o)) { size = static_cast(PySequence_Size(o)); } } return size; } //-------------------------------------------------------------------- // Check if 'm' equals 'n', and report an error for arg i if not. bool vtkPythonArgs::CheckSizeHint(int i, Py_ssize_t m, Py_ssize_t n) { if (this->M + i < this->N) { if (m != n) { PyObject *o = PyTuple_GET_ITEM(this->Args, this->M + i); return vtkPythonSequenceError(o, n, m); } } return true; } //-------------------------------------------------------------------- // Use stack space for small arrays, heap for large arrays. template vtkPythonArgs::Array::Array(Py_ssize_t n) : Pointer(nullptr) { if (n > basicsize) { this->Pointer = new T[n]; } else if (n != 0) { this->Pointer = this->Storage; } } // Instantiate the Array class template over all types: vtkPythonArgsTemplateMacro( template class VTKWRAPPINGPYTHONCORE_EXPORT vtkPythonArgs::Array )