vtkPythonUtil.cxx 75.6 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1
2
3
4
5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPythonUtil.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7
8
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Ken Martin's avatar
Ken Martin committed
9

10
11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12
     PURPOSE.  See the above copyright notice for more information.
Ken Martin's avatar
Ken Martin committed
13
14

=========================================================================*/
15

Andy Cedilnik's avatar
Andy Cedilnik committed
16
// This include allows VTK to build on some platforms with broken Python
17
// header files.
18
#include "vtkPythonUtil.h"
Ken Martin's avatar
Ken Martin committed
19

20
21
#include "vtkSystemIncludes.h"

22
#include "vtkDataArray.h"
Ken Martin's avatar
Ken Martin committed
23
#include "vtkObject.h"
24
#include "vtkObjectFactory.h"
25
26
#include "vtkSmartPointerBase.h"
#include "vtkTimeStamp.h"
27
#include "vtkWindows.h"
28

29
#include <vtksys/ios/sstream>
30
31
#include <vtkstd/map>
#include <vtkstd/string>
32

33
34
35
36
37
38
39
40
// Silent 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(__GNUG__) && (__GNUC__>4) || (__GNUC__==4 && __GNUC_MINOR__>=2)
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif

41
42
43
44
45
#if defined ( _MSC_VER )
#  define vtkConvertPtrToLong(x) ((long)(PtrToUlong(x)))
#else
#  define vtkConvertPtrToLong(x) ((long)(x))
#endif
Ken Martin's avatar
Ken Martin committed
46

47
48
49
50
// The following macro is used to supress missing initializer
// warnings.  Python documentation says these should not be necessary.
// We define it as a macro in case the length needs to change across
// python versions.
51
52
53
54
#if   PY_VERSION_HEX >= 0x02060000 // for tp_version_tag
#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \
  0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0, 0,
#elif   PY_VERSION_HEX >= 0x02030000
55
#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \
56
57
  0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,
#elif PY_VERSION_HEX >= 0x02020000
58
#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED \
59
  0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
60
61
62
#else
#define VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
#endif
63

64
65
66
67
#if PY_VERSION_HEX < 0x02050000
  typedef int Py_ssize_t;
#endif

Ken Martin's avatar
Ken Martin committed
68
69
//#define VTKPYTHONDEBUG

70
//--------------------------------------------------------------------
71
// There are two hash tables associated with the Python wrappers
72

73
class vtkPythonUtil
Ken Martin's avatar
Ken Martin committed
74
75
{
public:
76
77
  vtkPythonUtil();
  ~vtkPythonUtil();
Ken Martin's avatar
Ken Martin committed
78

79
80
  vtkstd::map<vtkSmartPointerBase, PyObject*> *ObjectHash;
  vtkstd::map<vtkstd::string, PyObject*> *ClassHash;
81
  vtkstd::map<vtkstd::string, PyVTKSpecialTypeInfo> *SpecialTypeHash;
Ken Martin's avatar
Ken Martin committed
82
83
};

84
85
86
87
88
//--------------------------------------------------------------------
vtkPythonUtil *vtkPythonHash = NULL;

//--------------------------------------------------------------------
vtkPythonUtil::vtkPythonUtil()
Ken Martin's avatar
Ken Martin committed
89
{
90
91
  this->ObjectHash = new vtkstd::map<vtkSmartPointerBase, PyObject*>;
  this->ClassHash = new vtkstd::map<vtkstd::string, PyObject*>;;
92
93
  this->SpecialTypeHash =
    new vtkstd::map<vtkstd::string, PyVTKSpecialTypeInfo>;
Ken Martin's avatar
Ken Martin committed
94
95
}

96
97
//--------------------------------------------------------------------
vtkPythonUtil::~vtkPythonUtil()
Ken Martin's avatar
Ken Martin committed
98
{
99
100
  delete this->ObjectHash;
  delete this->ClassHash;
101
  delete this->SpecialTypeHash;
Ken Martin's avatar
Ken Martin committed
102
103
}

104
//--------------------------------------------------------------------
Andy Cedilnik's avatar
Andy Cedilnik committed
105
extern "C" void vtkPythonHashDelete()
106
107
108
109
110
{
  delete vtkPythonHash;
  vtkPythonHash = 0;
}

111
//--------------------------------------------------------------------
112
static PyObject *PyVTKObject_PyString(PyVTKObject *self)
113
{
Andy Cedilnik's avatar
Andy Cedilnik committed
114
  PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__str__");
115

116
117
118
119
120
121
122
  if (func)
    {
    PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
    Py_DECREF(func);
    return res;
    }
  PyErr_Clear();
123

124
  vtksys_ios::ostringstream vtkmsg_with_warning_C4701;
125
126
  self->vtk_ptr->Print(vtkmsg_with_warning_C4701);
  vtkmsg_with_warning_C4701.put('\0');
127
  PyObject *res = PyString_FromString(vtkmsg_with_warning_C4701.str().c_str());
128
  return res;
129
130
}

131
//--------------------------------------------------------------------
132
static PyObject *PyVTKObject_PyRepr(PyVTKObject *self)
133
{
Andy Cedilnik's avatar
Andy Cedilnik committed
134
  PyObject *func = PyObject_GetAttrString((PyObject *)self, (char*)"__repr__");
135
136
137
138
139
140
141
142
143

  if (func)
    {
    PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
    Py_DECREF(func);
    return res;
    }
  PyErr_Clear();

144
145
  char buf[255];
  sprintf(buf,"<%s.%s %s at %p>",
146
147
          PyString_AsString(self->vtk_class->vtk_module),
          PyString_AsString(self->vtk_class->vtk_name),
148
          self->ob_type->tp_name,self);
149
150
151
152
  
  return PyString_FromString(buf);
}

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//--------------------------------------------------------------------
int PyVTKObject_PySetAttr(PyVTKObject *self, PyObject *attr,
                          PyObject *value)
{
  char *name = PyString_AsString(attr);

  if (name[0] == '_' && name[1] == '_')
    {
    if (strcmp(name, "__dict__") == 0)
      {
      PyErr_SetString(PyExc_RuntimeError,
                      "__dict__ is a read-only attribute");
      return -1;
      }
    if (strcmp(name, "__class__") == 0)
      {
      PyErr_SetString(PyExc_RuntimeError,
                      "__class__ is a read-only attribute");
      return -1;
      }
    }
  
  if (value)
    {
    PyObject *func = self->vtk_class->vtk_setattr;
    if (func)
      {
Andy Cedilnik's avatar
Andy Cedilnik committed
180
      PyObject *args = Py_BuildValue((char*)"(OOO)", self, attr, value);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
      PyObject *res = PyEval_CallObject(func, args);
      Py_DECREF(args);
      if (res)
        {
        Py_DECREF(res);
        return 0;
        }
      return -1;
      }
    return PyDict_SetItem(self->vtk_dict, attr, value);
    }
  else
    {
    PyObject *func = self->vtk_class->vtk_delattr;
    if (func)
      {
Andy Cedilnik's avatar
Andy Cedilnik committed
197
      PyObject *args = Py_BuildValue((char*)"(OO)", self, attr);
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
      PyObject *res = PyEval_CallObject(func, args);
      Py_DECREF(args);
      if (res)
        {
        Py_DECREF(res);
        return 0;
        }
      return -1;
      }
    int rv = PyDict_DelItem(self->vtk_dict, attr);
    if (rv < 0)
      {
      PyErr_SetString(PyExc_AttributeError,
                      "delete non-existing class attribute");
      }
    return rv;
    }
}

//--------------------------------------------------------------------
static PyObject *PyVTKObject_PyGetAttr(PyVTKObject *self, PyObject *attr)
219
{
220
221
  char *name = PyString_AsString(attr);
  PyVTKClass *pyclass = self->vtk_class;
222
  PyObject *bases;
223
224
225
226
227
228
229
  PyObject *value;

  if ((value = PyDict_GetItem(self->vtk_dict, attr)))
    {
    Py_INCREF(value);
    return value;
    }
230
231
232

  if (name[0] == '_')
    {
David Gobbi's avatar
David Gobbi committed
233
234
    if (strcmp(name,"__class__") == 0)
      {
235
236
      Py_INCREF(self->vtk_class);
      return (PyObject *)self->vtk_class;
David Gobbi's avatar
David Gobbi committed
237
      }
Jon Davis's avatar
Jon Davis committed
238
      
David Gobbi's avatar
David Gobbi committed
239
240
241
    if (strcmp(name,"__this__") == 0)
      {
      char buf[256];
242
      sprintf(buf,"p_%s", self->vtk_ptr->GetClassName());
243
      return PyString_FromString(vtkPythonManglePointer(self->vtk_ptr,buf));
David Gobbi's avatar
David Gobbi committed
244
245
246
247
      }

    if (strcmp(name,"__doc__") == 0)
      {
248
249
250
251
252
253
254
255
      Py_INCREF(pyclass->vtk_doc);
      return pyclass->vtk_doc;
      }

    if (strcmp(name,"__dict__") == 0)
      {
      Py_INCREF(self->vtk_dict);
      return self->vtk_dict;
David Gobbi's avatar
David Gobbi committed
256
      }
257
    }
David Gobbi's avatar
David Gobbi committed
258

259
260
  while (pyclass != NULL)
    {
261
    PyMethodDef *meth;
262

263
    if (pyclass->vtk_dict == NULL)
264
      {
265
266
267
      pyclass->vtk_dict = PyDict_New();

      for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++)
268
        {
269
270
        PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name,
                             PyCFunction_New(meth, (PyObject *)pyclass));
271
272
273
        }
      }

274
275
276
    value = PyDict_GetItem(pyclass->vtk_dict, attr);
    
    if (value)
David Gobbi's avatar
David Gobbi committed
277
      {
278
279
280
281
282
283
      if (PyCFunction_Check(value))
        {
        return PyCFunction_New(((PyCFunctionObject *)value)->m_ml,
                               (PyObject *)self);
        }
      else if (PyCallable_Check(value))
284
        {
285
286
        return PyMethod_New(value, (PyObject *)self,
                            (PyObject *)self->vtk_class);
287
        }
288
289
290
291
      Py_INCREF(value);
      return value;
      }

David Gobbi's avatar
David Gobbi committed
292
293
294
295
296
297
    bases = ((PyVTKClass *)pyclass)->vtk_bases;
    pyclass = NULL;
    if (PyTuple_Size(bases))
      {
      pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0);
      }
298
    }
David Gobbi's avatar
David Gobbi committed
299

300
301
302
303
  // try the __getattr__ attribute if set
  pyclass = self->vtk_class;
  if (pyclass->vtk_getattr)
    {
Andy Cedilnik's avatar
Andy Cedilnik committed
304
    PyObject *args = Py_BuildValue((char*)"(OO)", self, attr);
305
306
307
308
309
    PyObject *res = PyEval_CallObject(pyclass->vtk_getattr, args);
    Py_DECREF(args);
    return res;
    }

310
  PyErr_SetString(PyExc_AttributeError, name);
311
312
313
  return NULL;
}

314
315
316
//--------------------------------------------------------------------
static void PyVTKObject_PyDelete(PyVTKObject *self)
{
317
318
319
320
321
322
#if PY_VERSION_HEX >= 0x02010000
  if (self->vtk_weakreflist != NULL)
    {
    PyObject_ClearWeakRefs((PyObject *) self);
    }
#endif
323
324
325

  // A python object owning a VTK object reference is getting
  // destroyed.  Remove the python object's VTK object reference.
326
  vtkPythonDeleteObjectFromHash((PyObject *)self);
327

328
329
  Py_DECREF((PyObject *)self->vtk_class);
  Py_DECREF(self->vtk_dict);
330
331
332
#if (PY_MAJOR_VERSION >= 2)
  PyObject_Del(self);
#else
333
  PyMem_DEL(self);
334
#endif  
335
336
}

337
338
339
340
341
342
//--------------------------------------------------------------------
// The following methods and struct define the "buffer" protocol
// for PyVTKObject, so that python can read from a vtkDataArray.
// This is particularly useful for NumPy.

//--------------------------------------------------------------------
343
static Py_ssize_t
344
345
PyVTKObject_AsBuffer_GetSegCount(
  PyObject *pself, Py_ssize_t *lenp)
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
{
  PyVTKObject *self = (PyVTKObject*)pself;
  vtkDataArray *da = vtkDataArray::SafeDownCast(self->vtk_ptr);
  if (da)
    {
    if (lenp)
      {
      *lenp = da->GetNumberOfTuples()*
        da->GetNumberOfComponents()*
        da->GetDataTypeSize();
      }

    return 1;
    }

  if (lenp)
    {
    *lenp = 0;
    }
  return 0;
}

368
//--------------------------------------------------------------------
369
static Py_ssize_t
370
371
PyVTKObject_AsBuffer_GetReadBuf(
  PyObject *pself, Py_ssize_t segment, void **ptrptr)
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
{
  if (segment != 0) 
    {
    PyErr_SetString(PyExc_ValueError,
                    "accessing non-existing array segment");
    return -1;
    }

  PyVTKObject *self = (PyVTKObject*)pself;
  vtkDataArray *da = vtkDataArray::SafeDownCast(self->vtk_ptr);
  if (da)
    {
    *ptrptr = da->GetVoidPointer(0);
    return da->GetNumberOfTuples()*
      da->GetNumberOfComponents()*
      da->GetDataTypeSize();
    }
  return -1;
}

392
//--------------------------------------------------------------------
393
static Py_ssize_t
394
395
PyVTKObject_AsBuffer_GetWriteBuf(
  PyObject *pself, Py_ssize_t segment, void **ptrptr)
396
{
397
  return PyVTKObject_AsBuffer_GetReadBuf(pself, segment, ptrptr);
398
399
}

400
//--------------------------------------------------------------------
401
static Py_ssize_t
402
PyVTKObject_AsBuffer_GetCharBuf(PyObject *, Py_ssize_t , const char **)
403
404
405
406
{
  return -1;
}

407
408
//--------------------------------------------------------------------
static PyBufferProcs PyVTKObject_AsBuffer = {
409
#if PY_VERSION_HEX >= 0x02050000
410
411
412
413
414
415
416
417
  (readbufferproc)PyVTKObject_AsBuffer_GetReadBuf,     // bf_getreadbuffer
  (writebufferproc)PyVTKObject_AsBuffer_GetWriteBuf,   // bf_getwritebuffer
  (segcountproc)PyVTKObject_AsBuffer_GetSegCount,      // bf_getsegcount
  (charbufferproc)PyVTKObject_AsBuffer_GetCharBuf,     // bf_getcharbuffer
 #if PY_VERSION_HEX >= 0x02060000
  (getbufferproc)0,                                    // bf_getbuffer
  (releasebufferproc)0                                 // bf_releasebuffer
 #endif
418
#else
419
420
421
422
  (getreadbufferproc)PyVTKObject_AsBuffer_GetReadBuf,  // bf_getreadbuffer
  (getwritebufferproc)PyVTKObject_AsBuffer_GetWriteBuf,// bf_getwritebuffer
  (getsegcountproc)PyVTKObject_AsBuffer_GetSegCount,   // bf_getsegcount
  (getcharbufferproc)PyVTKObject_AsBuffer_GetCharBuf,  // bf_getcharbuffer
423
424
425
#endif
};

426
427
//--------------------------------------------------------------------
static PyTypeObject PyVTKObjectType = {
428
  PyObject_HEAD_INIT(&PyType_Type)
429
  0,
430
  (char*)"vtkobject",                    // tp_name
431
432
433
  sizeof(PyVTKObject),                   // tp_basicsize
  0,                                     // tp_itemsize
  (destructor)PyVTKObject_PyDelete,      // tp_dealloc
434
435
  (printfunc)0,                          // tp_print
  (getattrfunc)0,                        // tp_getattr
436
437
438
439
440
441
442
  (setattrfunc)0,                        // tp_setattr
  (cmpfunc)0,                            // tp_compare
  (reprfunc)PyVTKObject_PyRepr,          // tp_repr
  0,                                     // tp_as_number 
  0,                                     // tp_as_sequence
  0,                                     // tp_as_mapping
  (hashfunc)0,                           // tp_hash
443
  (ternaryfunc)0,                        // tp_call
444
  (reprfunc)PyVTKObject_PyString,        // tp_string
445
446
  (getattrofunc)PyVTKObject_PyGetAttr,   // tp_getattro
  (setattrofunc)PyVTKObject_PySetAttr,   // tp_setattro
447
  &PyVTKObject_AsBuffer,                 // tp_as_buffer
448
449
450
#if PY_VERSION_HEX >= 0x02010000
  Py_TPFLAGS_HAVE_WEAKREFS,              // tp_flags
#else
451
  0,                                     // tp_flags
452
#endif 
453
  (char*)"A VTK object.  Special attributes are:  __class__ (the class that this object belongs to), __dict__ (user-controlled attributes), __doc__ (the docstring for the class), __methods__ (a list of all methods for this object), and __this__ (a string that contains the hexidecimal address of the underlying VTK object)",  // tp_doc
454
455
456
457
458
459
460
461
  0,                                     // tp_traverse
  0,                                     // tp_clear
  0,                                     // tp_richcompare
#if PY_VERSION_HEX >= 0x02010000
  offsetof(PyVTKObject, vtk_weakreflist),// tp_weaklistoffset
#else
  0,                                     // tp_weaklistoffset
#endif
462
  VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
463
464
465
466
467
468
469
};

int PyVTKObject_Check(PyObject *obj)
{
  return (obj->ob_type == &PyVTKObjectType);
}

470
PyObject *PyVTKObject_New(PyObject *pyvtkclass, vtkObjectBase *ptr)
471
{
472
  PyVTKClass *vtkclass = (PyVTKClass *)pyvtkclass;
473
  bool haveRef = false;
474
  if (!ptr)
475
    {
476
477
478
479
480
481
482
483
484
485
486
487
488
    // Create a new instance of this class since we were not given one.
    if(vtkclass->vtk_new)
      {
      ptr = vtkclass->vtk_new();
      haveRef = true;
      }
    else
      {
      PyErr_SetString(
        PyExc_TypeError,
        (char*)"this is an abstract class and cannot be instantiated");
      return 0;
      }
489
    }
490
491
492
#if (PY_MAJOR_VERSION >= 2)
  PyVTKObject *self = PyObject_New(PyVTKObject, &PyVTKObjectType);
#else
493
  PyVTKObject *self = PyObject_NEW(PyVTKObject, &PyVTKObjectType);
494
#endif  
495
  self->vtk_ptr = ptr;
496
  PyObject *cls = NULL;
497
498
  vtkstd::map<vtkstd::string, PyObject*>::iterator i =
    vtkPythonHash->ClassHash->find(ptr->GetClassName());
499
  if (i != vtkPythonHash->ClassHash->end())
500
501
502
    {
    cls = i->second;
    }
503
  self->vtk_class = (PyVTKClass *)cls;
Jon Davis's avatar
Jon Davis committed
504
  
505
506
507
  // If the class was not in the dictionary (i.e. if there is no 'python'
  // level class to support the VTK level class) we fall back to this.
  if (self->vtk_class == NULL || vtkclass->vtk_methods == NULL)
508
    {
509
    self->vtk_class = vtkclass;
510
    }
Jon Davis's avatar
Jon Davis committed
511
  
512
  Py_INCREF(self->vtk_class);
Jon Davis's avatar
Jon Davis committed
513
  
514
515
  self->vtk_dict = PyDict_New();

516
517
518
519
#if PY_VERSION_HEX >= 0x02010000
  self->vtk_weakreflist = NULL;
#endif

520
521
  // A python object owning a VTK object reference is getting
  // created.  Add the python object's VTK object reference.
522
  vtkPythonAddObjectToHash((PyObject *)self, ptr);
523
524

  // The hash now owns a reference so we can free ours.
525
  if (haveRef)
526
527
528
529
    {
    ptr->Delete();
    }

530
531
532
533
  return (PyObject *)self;
}

//--------------------------------------------------------------------
534
static PyObject *PyVTKClass_PyString(PyVTKClass *self)
535
536
{
  char buf[255];
537
538
539
  sprintf(buf,"%s.%s",
          PyString_AsString(self->vtk_module),
          PyString_AsString(self->vtk_name));
540
541
542
543

  return PyString_FromString(buf);
}

544
//--------------------------------------------------------------------
545
static PyObject *PyVTKClass_PyRepr(PyVTKClass *self)
546
547
548
{
  char buf[255];
  sprintf(buf,"<%s %s.%s at %p>",self->ob_type->tp_name,
549
550
551
          PyString_AsString(self->vtk_module),
          PyString_AsString(self->vtk_name),
          self);
552
553
554
555
556
  
  return PyString_FromString(buf);
}

//--------------------------------------------------------------------
557
558
static PyObject *PyVTKClass_PyCall(PyVTKClass *self, PyObject *arg,
                                   PyObject *kw)
559
{
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  static PyObject *initstr = 0;

  if (((PyVTKClass *)self)->vtk_dict)
    {
    if (initstr == 0)
      {
      initstr = PyString_FromString("__init__");
      }

    PyObject *initfunc;
    initfunc = PyDict_GetItem(self->vtk_dict, initstr);

    if (initfunc)
      {      
      PyObject *obj = PyVTKObject_New((PyObject *)self,NULL);
575
576
      PyObject *cinitfunc = PyVTKObject_PyGetAttr((PyVTKObject *)obj, initstr);
      PyObject *res = PyEval_CallObjectWithKeywords(cinitfunc, arg, kw);
577
578
579
580
581
582
583
584
585
586
587
      if (res == NULL)
        {
        Py_DECREF(obj);
        obj = NULL;
        }
      else if (res != Py_None)
        {
        PyErr_SetString(PyExc_TypeError, "__init__() should return None");
        Py_DECREF(obj);
        obj = NULL;
        }
588
      Py_DECREF(cinitfunc);
589
590
591
592
      return obj;
      }
    }

593
594
  if (kw != NULL)
    {
595
596
597
    PyErr_SetString(PyExc_TypeError,
                    "this function takes no keyword arguments");
    return NULL;
598
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
599
  if (PyArg_ParseTuple(arg,(char*)""))
600
    {
601
    return PyVTKObject_New((PyObject *)self, NULL);
602
    }
603
  PyErr_Clear();
Andy Cedilnik's avatar
Andy Cedilnik committed
604
  if (PyArg_ParseTuple(arg,(char*)"O", &arg))
605
    {
606
607
    return vtkPythonGetObjectFromObject(arg,
                                        PyString_AsString(self->vtk_name));
608
609
610
    }
  PyErr_Clear();
  PyErr_SetString(PyExc_TypeError,
611
                  "function requires 0 or 1 arguments");
612

613
614
615
616
  return NULL;
}

//--------------------------------------------------------------------
617
static PyObject *PyVTKClass_PyGetAttr(PyVTKClass *self, PyObject *attr)
618
{
619
620
  char *name = PyString_AsString(attr);
  PyVTKClass *pyclass = self;
621
  PyObject *bases;
622

623
624
625
  while (pyclass != NULL)
    {
    PyMethodDef *meth;
626
    PyObject *value;
627

628
    if (pyclass->vtk_dict == NULL)
629
      {
630
      pyclass->vtk_dict = PyDict_New();
631

632
      for (meth = pyclass->vtk_methods; meth && meth->ml_name; meth++)
633
        {
634
635
        PyDict_SetItemString(pyclass->vtk_dict,meth->ml_name,
                             PyCFunction_New(meth, (PyObject *)pyclass));
636
637
638
        }
      }

639
640
641
    value = PyDict_GetItem(pyclass->vtk_dict, attr);
    
    if (value)
642
      {
643
644
      Py_INCREF(value);
      return value;
645
646
647
648
649
650
651
652
653
654
      }

    bases = pyclass->vtk_bases;
    pyclass = NULL;
    if (PyTuple_Size(bases))
      {
      pyclass = (PyVTKClass *)PyTuple_GetItem(bases,0);
      }
    }

655
656
  if (name[0] == '_')
    {
657
658
    pyclass = (PyVTKClass *)self;

David Gobbi's avatar
David Gobbi committed
659
660
    if (strcmp(name,"__bases__") == 0)
      {
661
662
      Py_INCREF(pyclass->vtk_bases);
      return pyclass->vtk_bases;
David Gobbi's avatar
David Gobbi committed
663
664
665
666
      }

    if (strcmp(name,"__name__") == 0)
      {
667
668
      Py_INCREF(pyclass->vtk_name);
      return pyclass->vtk_name;
David Gobbi's avatar
David Gobbi committed
669
670
671
672
      }

    if (strcmp(name,"__module__") == 0)
      {
673
674
      Py_INCREF(pyclass->vtk_module);
      return pyclass->vtk_module;
David Gobbi's avatar
David Gobbi committed
675
676
      }

677
678
679
680
681
682
    if (strcmp(name,"__dict__") == 0 && pyclass->vtk_dict)
      {
      Py_INCREF(pyclass->vtk_dict);
      return pyclass->vtk_dict;
      }
      
David Gobbi's avatar
David Gobbi committed
683
684
    if (strcmp(name,"__doc__") == 0)
      {
685
686
      Py_INCREF(pyclass->vtk_doc);
      return pyclass->vtk_doc;
David Gobbi's avatar
David Gobbi committed
687
      }
688
    }
David Gobbi's avatar
David Gobbi committed
689

690
  PyErr_SetString(PyExc_AttributeError, name);
691
692
693
694
  return NULL;
}

//--------------------------------------------------------------------
695
696
697
698
699
700
701
702
703
704
705
706
707
static void PyVTKClass_PyDelete(PyVTKClass *self)
{
  Py_XDECREF(self->vtk_bases);
  Py_XDECREF(self->vtk_dict);
  Py_XDECREF(self->vtk_name);

  Py_XDECREF(self->vtk_getattr);
  Py_XDECREF(self->vtk_setattr);
  Py_XDECREF(self->vtk_delattr);

  Py_XDECREF(self->vtk_module);
  Py_XDECREF(self->vtk_doc);
    
708
709
710
#if (PY_MAJOR_VERSION >= 2)
  PyObject_Del(self);
#else
711
  PyMem_DEL(self);
712
#endif  
713
714
715
716
}

//--------------------------------------------------------------------
static PyObject *PyVTKClassMetaType_GetAttr(PyTypeObject *t, char *name)
717
{
718
  if (strcmp(name, "__name__") == 0)
719
    {
720
    return PyString_FromString(t->tp_name);
721
    }
722
723
  if (strcmp(name, "__doc__") == 0)
    {
724
    const char *doc = t->tp_doc;
725
726
727
728
729
730
731
732
733
    if (doc != NULL)
      {
      return PyString_FromString(doc);
      }
    Py_INCREF(Py_None);
    return Py_None;
    }
  if (strcmp(name, "__members__") == 0)
    {
Andy Cedilnik's avatar
Andy Cedilnik committed
734
    return Py_BuildValue((char*)"[ss]", "__doc__", "__name__");
735
736
737
    }
  PyErr_SetString(PyExc_AttributeError, name);
  return NULL;
738
739
740
}

//--------------------------------------------------------------------
741
742
743
744
745
746
747
748
749
750
751
752
753
static PyObject *PyVTKClassMetaType_Repr(PyTypeObject *v)
{
  char buf[100];
  sprintf(buf, "<type '%.80s'>", v->tp_name);
  return PyString_FromString(buf);
}

//--------------------------------------------------------------------
static PyObject *PyVTKClass_NewSubclass(PyObject *self, PyObject *args,
                                        PyObject *kw);

//--------------------------------------------------------------------
PyTypeObject PyVTKClassMetaType = {
754
  PyObject_HEAD_INIT(&PyType_Type)
755
  0,                        /* Number of items for varobject */
756
  (char*)"vtkclass type",   /* Name of this type */
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
  sizeof(PyTypeObject),     /* Basic object size */
  0,                        /* Item size for varobject */
  0,                        /*tp_dealloc*/
  0,                        /*tp_print*/
  (getattrfunc)PyVTKClassMetaType_GetAttr, /*tp_getattr*/
  0,                        /*tp_setattr*/
  0,                        /*tp_compare*/
  (reprfunc)PyVTKClassMetaType_Repr,        /*tp_repr*/
  0,                        /*tp_as_number*/
  0,                        /*tp_as_sequence*/
  0,                        /*tp_as_mapping*/
  0,                        /*tp_hash*/
  (ternaryfunc)PyVTKClass_NewSubclass, /*tp_call*/
  0,                        /*tp_str*/
  0,                        /*tp_xxx1*/
  0,                        /*tp_xxx2*/
  0,                        /*tp_xxx3*/
  0,                        /*tp_xxx4*/
775
  (char*)"Define the behavior of a particular type of object.",
776
777
778
779
  0,                        // tp_traverse
  0,                        // tp_clear
  0,                        // tp_richcompare
  0,                        // tp_weaklistoffset
780
  VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
781
782
783
784
785
};

//--------------------------------------------------------------------
static PyTypeObject PyVTKClassType = {
  PyObject_HEAD_INIT(&PyVTKClassMetaType)
786
  0,
787
  (char*)"vtkclass",                     // tp_name
788
789
790
  sizeof(PyVTKClass),                    // tp_basicsize
  0,                                     // tp_itemsize
  (destructor)PyVTKClass_PyDelete,       // tp_dealloc
791
792
  (printfunc)0,                          // tp_print
  (getattrfunc)0,                        // tp_getattr
793
794
795
796
797
798
799
800
  (setattrfunc)0,                        // tp_setattr
  (cmpfunc)0,                            // tp_compare
  (reprfunc)PyVTKClass_PyRepr,           // tp_repr
  0,                                     // tp_as_number 
  0,                                     // tp_as_sequence
  0,                                     // tp_as_mapping
  (hashfunc)0,                           // tp_hash
  (ternaryfunc)PyVTKClass_PyCall,        // tp_call
801
  (reprfunc)PyVTKClass_PyString,         // tp_string
802
  (getattrofunc)PyVTKClass_PyGetAttr,    // tp_getattro
803
804
805
  (setattrofunc)0,                       // tp_setattro
  0,                                     // tp_as_buffer
  0,                                     // tp_flags
806
  (char*)"A generator for VTK objects.  Special attributes are: __bases__ (a tuple of base classes), __dict__ (user-defined methods and attributes), __doc__ (the docstring for the class), __name__ (the name of class), __methods__ (methods for this class, not including inherited methods or user-defined methods), and __module__ (module that the class is defined in).", // tp_doc
807
808
809
810
  0,                                     // tp_traverse
  0,                                     // tp_clear
  0,                                     // tp_richcompare
  0,                                     // tp_weaklistoffset
811
  VTK_PYTHON_UTIL_SUPRESS_UNINITIALIZED
812
813
814
815
816
817
818
};

int PyVTKClass_Check(PyObject *obj)
{
  return (obj->ob_type == &PyVTKClassType);
}

819
820
821
822
//--------------------------------------------------------------------
// Concatenate an array of strings into a single string.  The resulting
// string is allocated via new.  The array of strings must be null-terminated,
// e.g. static char *strings[] = {"string1", "string2", NULL};
823
static PyObject *vtkBuildDocString(char *docstring[])
824
{
825
  PyObject *result;
826
827
828
829
830
  char *data;
  int i, j, n;
  int *m;
  int total = 0;

Sean McBride's avatar
Sean McBride committed
831
832
833
834
  for (n = 0; docstring[n] != NULL; n++)
    {
    ;
    }
835
836
837
838
839

  m = new int[n];

  for (i = 0; i < n; i++)
    {
Andy Cedilnik's avatar
Andy Cedilnik committed
840
    m[i] = static_cast<int>(strlen(docstring[i]));
841
842
843
    total += m[i];
    }

844
  result = PyString_FromStringAndSize(docstring[0], m[0]);
845
  
846
847
848
849
850
851
852
853
854
  if (n > 1)
    {
    _PyString_Resize(&result, total);
    }

  data = PyString_AsString(result);
  
  j = m[0];
  for (i = 1; i < n; i++)
855
856
857
858
859
860
861
    {
    strcpy(&data[j], docstring[i]);
    j += m[i];
    }
  
  delete [] m;

862
  return result;
863
864
}

865
PyObject *PyVTKClass_New(vtknewfunc constructor,
866
                         PyMethodDef *methods,
867
                         char *classname, char *modulename, char *docstring[],
868
                         PyObject *base)
869
{
870
871
  static PyObject *modulestr[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 
  static int nmodulestr = 10;
872
  PyObject *moduleobj = 0;
873
  PyObject *self = NULL;
874
875
  int i;

876
877
  if (vtkPythonHash)
    {
878
    vtkstd::map<vtkstd::string, PyObject*>::iterator it =
879
      vtkPythonHash->ClassHash->find(classname);
880
    if(it != vtkPythonHash->ClassHash->end())
881
      {
882
      self = it->second;
883
      }
884
885
886
    }
  if (self)
    {
887
    Py_INCREF(self);
888
889
    }
  else
890
    {
891
892
893
#if (PY_MAJOR_VERSION >= 2)
    PyVTKClass *class_self = PyObject_New(PyVTKClass, &PyVTKClassType);
#else
894
    PyVTKClass *class_self = PyObject_NEW(PyVTKClass, &PyVTKClassType);
895
#endif  
896
    self = (PyObject *)class_self;
897
    
David Gobbi's avatar
David Gobbi committed
898
899
    if (base)
      {
900
901
      class_self->vtk_bases = PyTuple_New(1);
      PyTuple_SET_ITEM(class_self->vtk_bases, 0, base);
David Gobbi's avatar
David Gobbi committed
902
903
904
      }
    else
      {
905
      class_self->vtk_bases = PyTuple_New(0);
David Gobbi's avatar
David Gobbi committed
906
      }
907
908
    class_self->vtk_dict = NULL;
    class_self->vtk_name = PyString_FromString(classname);
909

910
911
912
    class_self->vtk_getattr = NULL;
    class_self->vtk_setattr = NULL;
    class_self->vtk_delattr = NULL;
913
    
914
915
916
    class_self->vtk_methods = methods;
    class_self->vtk_new = constructor;
    class_self->vtk_doc = vtkBuildDocString(docstring);
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939

    // intern the module string
    for (i = 0; i < nmodulestr; i++)
      {
      if (modulestr[i] == 0)
        {
        modulestr[i] = PyString_InternFromString(modulename);
        moduleobj = modulestr[i];
        Py_INCREF(moduleobj);
        break;
        }
      else if (strcmp(modulename,PyString_AsString(modulestr[i])) == 0)
        {
        moduleobj = modulestr[i];
        Py_INCREF(moduleobj);
        break;
        }
      }
    if (i == nmodulestr)
      {
      moduleobj = PyString_FromString(modulename);
      }

940
    class_self->vtk_module = moduleobj;
941

942
    vtkPythonAddClassToHash(self,classname);
943
    }
David Gobbi's avatar
David Gobbi committed
944

945
946
  return (PyObject *)self;
}
947

948
//--------------------------------------------------------------------
949
static PyObject *PyVTKClass_NewSubclass(PyObject *, PyObject *args,
950
                                        PyObject *kw)
951
{
952
  static const char *kwlist[] = {"name", "bases", "dict", NULL};
953
954
955
956
957
958
959
960

  PyVTKClass *newclass;
  char *classname;
  PyObject *globals;
  PyObject *bases;
  PyVTKClass *base;
  PyObject *attributes;

Andy Cedilnik's avatar
Andy Cedilnik committed
961
  if ((PyArg_ParseTupleAndKeywords(args, kw, (char*)"sOO", (char**)kwlist, 
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
                                   &classname, &bases, &attributes)))
    {
    if (!PyTuple_Check(bases) || PyTuple_Size(bases) != 1)
      {
      PyErr_SetString(PyExc_ValueError,
                      "multiple inheritence is not allowed with VTK classes");
      return NULL;
      }

    base = (PyVTKClass *)PyTuple_GetItem(bases,0);
    if (base == 0)
      {
      PyErr_SetString(PyExc_ValueError,"bases must be a tuple");
      return NULL;
      }

    if (!PyVTKClass_Check((PyObject *)base))
      {
      PyErr_SetString(PyExc_ValueError,"base class is not a VTK class");
      return NULL;
      }

    if (!PyDict_Check(attributes))
      {
      PyErr_SetString(PyExc_ValueError,"namespace not provided");
      return NULL;
      }

Andy Cedilnik's avatar
Andy Cedilnik committed
990
    if (PyDict_GetItemString(attributes, (char*)"__del__"))
991
992
993
994
995
      {
      PyErr_SetString(PyExc_ValueError, "__del__ attribute is not supported");
      return NULL;
      }

996
997
998
#if (PY_MAJOR_VERSION >= 2)
    newclass = PyObject_New(PyVTKClass, &PyVTKClassType);
#else
999
    newclass = PyObject_NEW(PyVTKClass, &PyVTKClassType);
1000
#endif  
1001
1002
1003
1004
1005
1006
1007
1008

    Py_INCREF(bases);
    Py_INCREF(attributes);

    newclass->vtk_bases = bases;
    newclass->vtk_dict = attributes;
    newclass->vtk_name = PyString_FromString(classname);

Andy Cedilnik's avatar
Andy Cedilnik committed
1009
    newclass->vtk_getattr = PyDict_GetItemString(attributes, (char*)"__getattr__");
1010
1011
1012
1013
1014
    if (newclass->vtk_getattr == 0)
      {
      newclass->vtk_getattr = base->vtk_getattr;
      }
    Py_XINCREF(newclass->vtk_getattr);
Andy Cedilnik's avatar
Andy Cedilnik committed
1015
    newclass->vtk_setattr = PyDict_GetItemString(attributes, (char*)"__setattr__");
1016
1017
1018
1019
1020
    if (newclass->vtk_setattr == 0)
      {
      newclass->vtk_setattr = base->vtk_setattr;
      }
    Py_XINCREF(newclass->vtk_setattr);
Andy Cedilnik's avatar
Andy Cedilnik committed
1021
    newclass->vtk_delattr = PyDict_GetItemString(attributes, (char*)"__delattr__");
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
    if (newclass->vtk_delattr == 0)
      {
      newclass->vtk_delattr = base->vtk_delattr;
      }
    Py_XINCREF(newclass->vtk_delattr);

    newclass->vtk_methods = NULL;
    newclass->vtk_new = base->vtk_new;
    newclass->vtk_module = NULL;
    newclass->vtk_doc = NULL;

    globals = PyEval_GetGlobals();
    if (globals != NULL)
      {
Andy Cedilnik's avatar
Andy Cedilnik committed
1036
      PyObject *modname = PyDict_GetItemString(globals, (char*)"__name__");
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
      if (modname != NULL)
        {
        Py_INCREF(modname);
        newclass->vtk_module = modname;
        }
      }
    if (newclass->vtk_module == NULL)
      {
      newclass->vtk_module = PyString_FromString("__main__");
      }

Andy Cedilnik's avatar
Andy Cedilnik committed
1048
    newclass->vtk_doc = PyDict_GetItemString(attributes, (char*)"__doc__");
1049
1050
1051
    if (newclass->vtk_doc)
      {
      Py_INCREF(newclass->vtk_doc);
Andy Cedilnik's avatar
Andy Cedilnik committed
1052
      PyDict_DelItemString(attributes, (char*)"__doc__");
1053
1054
1055
1056
1057
1058
1059
1060
1061
      }
    else
      {
      newclass->vtk_doc = PyString_FromString("");
      }

    return (PyObject *)newclass;    
    }
  return NULL;
1062
1063
1064
}

//--------------------------------------------------------------------
1065
static PyObject *PyVTKSpecialObject_PyString(PyVTKSpecialObject *self)
1066
{
1067
1068
1069
1070
  vtksys_ios::ostringstream os;
  self->vtk_info->print_func(os, self->vtk_ptr);
  const vtksys_stl::string &s = os.str();
  return PyString_FromStringAndSize(s.data(), s.size());
1071
1072
1073
}

//--------------------------------------------------------------------
1074
static PyObject *PyVTKSpecialObject_PyRepr(PyVTKSpecialObject *self)
1075
1076
1077
{
  char buf[255];
  sprintf(buf,"<%s %s at %p>", self->ob_type->tp_name, 
1078
          PyString_AsString(self->vtk_info->classname), self);
1079
1080
1081
1082
  return PyString_FromString(buf);
}

//--------------------------------------------------------------------
1083
1084
static PyObject *PyVTKSpecialObject_PyGetAttr(PyVTKSpecialObject *self,
                                              PyObject *attr)
1085
{
1086
  char *name = PyString_AsString(attr);
1087
1088
1089
1090
  PyMethodDef *meth;

  if (name[0] == '_')
    {
David Gobbi's avatar
David Gobbi committed
1091
1092
    if (strcmp(name,"__name__") == 0)
      {
1093
1094
      Py_INCREF(self->vtk_info->classname);
      return self->vtk_info->classname;