Commit 19d97caa authored by David Gobbi's avatar David Gobbi
Browse files

Wrap pass-by-reference for pointers.

Used in the vtkCellArray GetCell() and GetNextCell() methods.
parent c2fac23c
......@@ -29,6 +29,12 @@ class TestMutable(Testing.vtkTest):
m %= ("hello", "world")
self.assertEqual(m, "hello world!")
def testTupleMutable(self):
m = vtk.mutable((0,))
self.assertEqual(m, (0,))
self.assertEqual(len(m), 1)
self.assertEqual(m[0], 0)
def testPassByReference(self):
t = vtk.mutable(0.0)
p0 = (0.5, 0.0, 0.0)
......@@ -61,5 +67,14 @@ class TestMutable(Testing.vtkTest):
self.assertEqual(round(x[1],6), 0.5)
self.assertEqual(round(x[2],6), 0.5)
def testPassTupleByReference(self):
n = vtk.mutable(0)
t = vtk.mutable((0,))
ca = vtk.vtkCellArray()
ca.InsertNextCell(3, (1, 3, 0))
ca.GetCell(0, n, t)
self.assertEqual(n, 3)
self.assertEqual(tuple(t), (1, 3, 0))
if __name__ == "__main__":
Testing.main([(TestMutable, 'test')])
......@@ -135,6 +135,7 @@ void PyVTKAddFile_PyVTKExtras(PyObject *dict)
// It is necessary to call PyType_Ready() on all subclasses
PyType_Ready(&PyVTKMutableNumber_Type);
PyType_Ready(&PyVTKMutableString_Type);
PyType_Ready(&PyVTKMutableTuple_Type);
// Add the "mutable" object (used for C++ pass-by-reference)
PyObject *o = (PyObject *)&PyVTKMutableObject_Type;
......
......@@ -71,6 +71,17 @@ static PyObject *PyVTKMutableObject_CompatibleObject(
}
}
// check if it is a tuple or list
if (self == nullptr || Py_TYPE(self) == &PyVTKMutableTuple_Type)
{
if (PyTuple_Check(opn) ||
PyList_Check(opn))
{
Py_INCREF(opn);
return opn;
}
}
// check if it is a number
if (self == nullptr || Py_TYPE(self) == &PyVTKMutableNumber_Type)
{
......@@ -121,12 +132,16 @@ static PyObject *PyVTKMutableObject_CompatibleObject(
const char *errmsg = "bad type";
if (self == nullptr)
{
errmsg = "a numeric or string object is required";
errmsg = "a numeric, string, or tuple object is required";
}
else if (Py_TYPE(self) == &PyVTKMutableString_Type)
{
errmsg = "a string object is required";
}
else if (Py_TYPE(self) == &PyVTKMutableTuple_Type)
{
errmsg = "a tuple object is required";
}
else if (Py_TYPE(self) == &PyVTKMutableNumber_Type)
{
errmsg = "a numeric object is required";
......@@ -969,6 +984,12 @@ static PyObject *PyVTKMutableObject_New(
self = PyObject_New(PyVTKMutableObject,
&PyVTKMutableString_Type);
}
else if (PyTuple_Check(o) ||
PyList_Check(o))
{
self = PyObject_New(PyVTKMutableObject,
&PyVTKMutableTuple_Type);
}
else
{
self = PyObject_New(PyVTKMutableObject,
......@@ -1152,3 +1173,60 @@ PyTypeObject PyVTKMutableString_Type = {
nullptr, // tp_weaklist
VTK_WRAP_PYTHON_SUPPRESS_UNINITIALIZED
};
//--------------------------------------------------------------------
PyTypeObject PyVTKMutableTuple_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"vtkCommonCorePython.mutable_tuple", // tp_name
sizeof(PyVTKMutableObject), // tp_basicsize
0, // tp_itemsize
PyVTKMutableObject_Delete, // tp_dealloc
nullptr, // tp_print
nullptr, // tp_getattr
nullptr, // tp_setattr
nullptr, // tp_compare
PyVTKMutableObject_Repr, // tp_repr
nullptr, // tp_as_number
&PyVTKMutableObject_AsSequence, // tp_as_sequence
&PyVTKMutableObject_AsMapping, // tp_as_mapping
#if PY_VERSION_HEX >= 0x02060000
PyObject_HashNotImplemented, // tp_hash
#else
nullptr, // tp_hash
#endif
nullptr, // tp_call
PyVTKMutableObject_Str, // tp_string
PyVTKMutableObject_GetAttr, // tp_getattro
nullptr, // tp_setattro
nullptr, // tp_as_buffer
#ifndef VTK_PY3K
Py_TPFLAGS_CHECKTYPES |
#endif
Py_TPFLAGS_DEFAULT, // tp_flags
PyVTKMutableObject_Doc, // tp_doc
nullptr, // tp_traverse
nullptr, // tp_clear
PyVTKMutableObject_RichCompare, // tp_richcompare
0, // tp_weaklistoffset
PyVTKMutableObject_GetIter, // tp_iter
nullptr, // tp_iternext
PyVTKMutableObject_Methods, // tp_methods
nullptr, // tp_members
nullptr, // tp_getset
(PyTypeObject *)&PyVTKMutableObject_Type, // tp_base
nullptr, // tp_dict
nullptr, // tp_descr_get
nullptr, // tp_descr_set
0, // tp_dictoffset
nullptr, // tp_init
nullptr, // tp_alloc
PyVTKMutableObject_New, // tp_new
PyObject_Del, // tp_free
nullptr, // tp_is_gc
nullptr, // tp_bases
nullptr, // tp_mro
nullptr, // tp_cache
nullptr, // tp_subclasses
nullptr, // tp_weaklist
VTK_WRAP_PYTHON_SUPPRESS_UNINITIALIZED
};
......@@ -36,6 +36,7 @@ struct PyVTKMutableObject {
extern VTKWRAPPINGPYTHONCORE_EXPORT PyTypeObject PyVTKMutableObject_Type;
extern VTKWRAPPINGPYTHONCORE_EXPORT PyTypeObject PyVTKMutableNumber_Type;
extern VTKWRAPPINGPYTHONCORE_EXPORT PyTypeObject PyVTKMutableString_Type;
extern VTKWRAPPINGPYTHONCORE_EXPORT PyTypeObject PyVTKMutableTuple_Type;
#define PyVTKMutableObject_Check(obj) \
PyObject_TypeCheck(obj, &PyVTKMutableObject_Type)
......
......@@ -1215,6 +1215,24 @@ bool vtkPythonArgs::SetArgValue(int i, T a) \
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 = PyVTKMutableObject_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)
......@@ -1231,6 +1249,19 @@ 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
......
......@@ -425,7 +425,7 @@ public:
//@{
/**
* Set the value of an argument if it is an assignable type.
* Set the value of an argument that was passed by reference.
*/
bool SetArgValue(int i, const std::string &v);
bool SetArgValue(int i, const vtkUnicodeString &v);
......@@ -443,6 +443,19 @@ public:
bool SetArgValue(int i, unsigned long v);
bool SetArgValue(int i, long long v);
bool SetArgValue(int i, unsigned long long v);
bool SetArgValue(int i, const float *v, int n);
bool SetArgValue(int i, const double *v, int n);
bool SetArgValue(int i, const bool *v, int n);
bool SetArgValue(int i, const signed char *v, int n);
bool SetArgValue(int i, const unsigned char *v, int n);
bool SetArgValue(int i, const short *v, int n);
bool SetArgValue(int i, const unsigned short *v, int n);
bool SetArgValue(int i, const int *v, int n);
bool SetArgValue(int i, const unsigned int *v, int n);
bool SetArgValue(int i, const long *v, int n);
bool SetArgValue(int i, const unsigned long *v, int n);
bool SetArgValue(int i, const long long *v, int n);
bool SetArgValue(int i, const unsigned long long *v, int n);
//@}
//@{
......
......@@ -51,7 +51,7 @@ static void vtkWrapPython_GenerateMethodCall(
/* Write back to all the reference arguments and array arguments */
static void vtkWrapPython_WriteBackToArgs(
FILE *fp, FunctionInfo *currentFunction);
FILE *fp, ClassInfo *data, FunctionInfo *currentFunction);
/* Free any arrays, object, or buffers that were allocated */
static void vtkWrapPython_FreeTemporaries(
......@@ -120,7 +120,8 @@ void vtkWrapPython_DeclareVariables(
i, i,
vtkWrap_GetTypeName(arg), i, mtwo, i,
vtkWrap_GetTypeName(arg), i, i);
if (!vtkWrap_IsConst(arg))
if (!vtkWrap_IsConst(arg) &&
!vtkWrap_IsRef(arg))
{
fprintf(fp,
" %s *save%d = (size%d == 0 ? nullptr : temp%d + size%d);\n",
......@@ -399,7 +400,7 @@ static void vtkWrapPython_GetAllParameters(
{
arg = currentFunction->Parameters[i];
if (arg->CountHint)
if (arg->CountHint && !vtkWrap_IsRef(arg))
{
fprintf(fp, " &&\n"
" ap.CheckSizeHint(%d, size%d, ",
......@@ -787,7 +788,8 @@ void vtkWrapPython_SaveArrayArgs(FILE *fp, FunctionInfo *currentFunction)
if ((vtkWrap_IsArray(arg) || vtkWrap_IsNArray(arg) ||
vtkWrap_IsPODPointer(arg)) &&
(arg->Type & VTK_PARSE_CONST) == 0)
(arg->Type & VTK_PARSE_CONST) == 0 &&
!vtkWrap_IsRef(arg))
{
noneDone = 0;
......@@ -1015,7 +1017,7 @@ static void vtkWrapPython_GenerateMethodCall(
* were passed, but only write to arrays if the array has changed and
* the array arg was non-const */
static void vtkWrapPython_WriteBackToArgs(
FILE *fp, FunctionInfo *currentFunction)
FILE *fp, ClassInfo *data, FunctionInfo *currentFunction)
{
const char *asterisks = "**********";
ValueInfo *arg;
......@@ -1044,12 +1046,34 @@ static void vtkWrapPython_WriteBackToArgs(
{
fprintf(fp,
" if (!ap.ErrorOccurred())\n"
" {\n"
" ap.SetArgValue(%d, temp%d);\n"
" }\n",
" {\n");
if (vtkWrap_IsArray(arg) ||
vtkWrap_IsPODPointer(arg))
{
fprintf(fp,
" ap.SetArgValue(%d, temp%d, ",
i, i);
if (arg->CountHint)
{
vtkWrapPython_SubstituteCode(fp, data, currentFunction,
arg->CountHint);
}
else
{
fprintf(fp, "size%d", i);
}
fprintf(fp, ");\n");
}
else
{
fprintf(fp,
" ap.SetArgValue(%d, temp%d);\n",
i, i);
}
fprintf(fp,
" }\n");
}
else if ((vtkWrap_IsArray(arg) || vtkWrap_IsNArray(arg) ||
vtkWrap_IsPODPointer(arg)) &&
!vtkWrap_IsConst(arg) &&
......@@ -1282,7 +1306,7 @@ void vtkWrapPython_GenerateOneMethod(
is_vtkobject);
/* write back to all array args */
vtkWrapPython_WriteBackToArgs(fp, theOccurrence);
vtkWrapPython_WriteBackToArgs(fp, data, theOccurrence);
/* generate the code that builds the return value */
if (do_constructors && !is_vtkobject)
......
......@@ -493,7 +493,10 @@ static int vtkWrapPython_IsValueWrappable(
return 0;
}
if (vtkWrap_IsRef(val) && !vtkWrap_IsScalar(val))
if (vtkWrap_IsRef(val) &&
!vtkWrap_IsScalar(val) &&
!vtkWrap_IsArray(val) &&
!vtkWrap_IsPODPointer(val))
{
return 0;
}
......
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