vtkPythonUtil.cxx 28.7 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

16
#include "vtkPythonUtil.h"
17
#include "vtkPythonOverload.h"
Ken Martin's avatar
Ken Martin committed
18

19
20
#include "vtkSystemIncludes.h"

Ken Martin's avatar
Ken Martin committed
21
#include "vtkObject.h"
22
#include "vtkPythonCommand.h"
23
#include "vtkSmartPointerBase.h"
24
#include "vtkStdString.h"
25
#include "vtkToolkits.h"
26
#include "vtkUnicodeString.h"
27
28
#include "vtkVariant.h"
#include "vtkWeakPointer.h"
29
#include "vtkWindows.h"
30

31
#include <cstring>
32
#include <sstream>
33
34
35
36
#include <map>
#include <vector>
#include <string>
#include <utility>
37
#include <algorithm>
38

39
40
41
42
// for uintptr_t
#ifdef _MSC_VER
#include <stddef.h>
#else
43
#include <cstdint>
44
#endif
45
46
47
48
49
50

//--------------------------------------------------------------------
// A ghost object, can be used to recreate a deleted PyVTKObject
class PyVTKObjectGhost
{
public:
51
  PyVTKObjectGhost() : vtk_ptr(), vtk_class(nullptr), vtk_dict(nullptr) {};
52
53

  vtkWeakPointerBase vtk_ptr;
54
  PyTypeObject *vtk_class;
55
56
57
  PyObject *vtk_dict;
};

58
//--------------------------------------------------------------------
59
// There are six maps associated with the Python wrappers
60

61
62
63
// Map VTK objects to python objects (this is also the cornerstone
// of the vtk/python garbage collection system, because it contains
// exactly one pointer reference for each VTK object known to python)
64
class vtkPythonObjectMap
65
  : public std::map<vtkObjectBase*, std::pair<PyObject *, vtkAtomicInt32> >
66
{
67
68
public:
  ~vtkPythonObjectMap();
69
70
71

  void add(vtkObjectBase* key, PyObject* value);
  void remove(vtkObjectBase* key);
72
};
73

74
75
76
77
// Call Delete instead of relying on vtkSmartPointer, so that crashes
// caused by deletion are easier to follow in the debug stack trace
vtkPythonObjectMap::~vtkPythonObjectMap()
{
Ben Boeckel's avatar
Ben Boeckel committed
78
  iterator i;
79
  for (i = this->begin(); i != this->end(); ++i)
80
  {
81
    for (int j = 0; j < i->second.second; ++j)
82
    {
83
84
      i->first->Delete();
    }
85
  }
86
87
88
89
90
}

void
vtkPythonObjectMap::add(vtkObjectBase* key, PyObject* value)
{
91
  key->Register(nullptr);
92
93
  iterator i = this->find(key);
  if (i == this->end())
94
  {
95
    (*this)[key] = std::make_pair(value, 1);
96
  }
97
  else
98
  {
99
100
    i->second.first = value;
    ++i->second.second;
101
  }
102
103
104
105
106
107
108
}

void
vtkPythonObjectMap::remove(vtkObjectBase* key)
{
  iterator i = this->find(key);
  if (i != this->end())
109
  {
110
111
112
113
114
    // Save the object. The iterator will become invalid if the iterator is
    // erased.
    vtkObjectBase* obj = i->first;
    // Remove it from the map if necessary.
    if (!--i->second.second)
115
    {
116
      this->erase(i);
117
    }
118
119
120
121
122
    // Remove a reference to the object. This must be done *after* removing it
    // from the map (if needed) because if there's a callback which reacts when
    // the reference is dropped, it might call RemoveObjectFromMap as well. If
    // it still exists in the map at that point, this becomes an infinite loop.
    obj->Delete();
123
  }
124
125
}

126
127
128
129
130
131
// Keep weak pointers to VTK objects that python no longer has
// references to.  Python keeps the python 'dict' for VTK objects
// even when they pass leave the python realm, so that if those
// VTK objects come back, their 'dict' can be restored to them.
// Periodically the weak pointers are checked and the dicts of
// VTK objects that have been deleted are tossed away.
132
class vtkPythonGhostMap
133
  : public std::map<vtkObjectBase*, PyVTKObjectGhost>
134
135
136
{
};

137
// Keep track of all the VTK classes that python knows about.
138
class vtkPythonClassMap
139
  : public std::map<std::string, PyVTKClass>
140
141
{
};
142

143
// Like the ClassMap, for types not derived from vtkObjectBase.
144
class vtkPythonSpecialTypeMap
145
  : public std::map<std::string, PyVTKSpecialType>
146
147
{
};
148

149
150
151
152
153
154
// Keep track of all the C++ namespaces that have been wrapped.
class vtkPythonNamespaceMap
  : public std::map<std::string, PyObject*>
{
};

155
156
157
158
159
160
// Keep track of all the C++ enums that have been wrapped.
class vtkPythonEnumMap
  : public std::map<std::string, PyTypeObject*>
{
};

161
162
163
164
165
166
// Keep track of all the VTK-Python extension modules
class vtkPythonModuleList
  : public std::vector<std::string>
{
};

167
168
169
170
171
172
// Keep track of all vtkPythonCommand instances.
class vtkPythonCommandList
  : public std::vector<vtkWeakPointer<vtkPythonCommand> >
{
public:
  ~vtkPythonCommandList()
173
  {
174
175
    iterator iter;
    for (iter = this->begin(); iter != this->end(); ++iter)
176
    {
177
      if (iter->GetPointer())
178
      {
179
180
        iter->GetPointer()->obj = nullptr;
        iter->GetPointer()->ThreadState = nullptr;
181
182
      }
    }
183
  }
184
  void findAndErase(vtkPythonCommand* ptr)
185
  {
186
    this->erase(std::remove(this->begin(), this->end(), ptr), this->end());
187
  }
188
};
189

190
191
//--------------------------------------------------------------------
// The singleton for vtkPythonUtil
192

193
static vtkPythonUtil *vtkPythonMap = nullptr;
194

195
196
197
198
// destructs the singleton when python exits
void vtkPythonUtilDelete()
{
  delete vtkPythonMap;
199
  vtkPythonMap = nullptr;
200
201
}

202
203
204
// constructs the singleton
void vtkPythonUtilCreateIfNeeded()
{
205
  if (vtkPythonMap == nullptr)
206
  {
207
208
    vtkPythonMap = new vtkPythonUtil();
    Py_AtExit(vtkPythonUtilDelete);
209
  }
210
211
}

212
//--------------------------------------------------------------------
213
vtkPythonUtil::vtkPythonUtil()
214
{
215
  this->ObjectMap = new vtkPythonObjectMap;
216
  this->GhostMap = new vtkPythonGhostMap;
217
218
  this->ClassMap = new vtkPythonClassMap;
  this->SpecialTypeMap = new vtkPythonSpecialTypeMap;
219
  this->NamespaceMap = new vtkPythonNamespaceMap;
220
  this->EnumMap = new vtkPythonEnumMap;
221
  this->ModuleList = new vtkPythonModuleList;
222
  this->PythonCommandList = new vtkPythonCommandList;
223
224
225
}

//--------------------------------------------------------------------
226
vtkPythonUtil::~vtkPythonUtil()
227
{
228
  delete this->ObjectMap;
229
  delete this->GhostMap;
230
231
  delete this->ClassMap;
  delete this->SpecialTypeMap;
232
  delete this->NamespaceMap;
233
  delete this->EnumMap;
234
  delete this->ModuleList;
235
  delete this->PythonCommandList;
236
237
}

238
239
240
241
//--------------------------------------------------------------------
void vtkPythonUtil::RegisterPythonCommand(vtkPythonCommand* cmd)
{
  if (cmd)
242
  {
243
244
    vtkPythonUtilCreateIfNeeded();
    vtkPythonMap->PythonCommandList->push_back(cmd);
245
  }
246
247
248
249
250
251
}

//--------------------------------------------------------------------
void vtkPythonUtil::UnRegisterPythonCommand(vtkPythonCommand* cmd)
{
  if (cmd && vtkPythonMap)
252
  {
253
    vtkPythonMap->PythonCommandList->findAndErase(cmd);
254
  }
255
256
}

257
//--------------------------------------------------------------------
258
PyTypeObject *vtkPythonUtil::AddSpecialTypeToMap(
259
  PyTypeObject *pytype, PyMethodDef *methods, PyMethodDef *constructors,
260
  vtkcopyfunc copyfunc)
261
{
262
  const char *classname = vtkPythonUtil::StripModule(pytype->tp_name);
263
  vtkPythonUtilCreateIfNeeded();
264
265

  // lets make sure it isn't already there
266
267
  vtkPythonSpecialTypeMap::iterator i =
    vtkPythonMap->SpecialTypeMap->find(classname);
268
  if (i == vtkPythonMap->SpecialTypeMap->end())
269
  {
270
271
272
273
    i = vtkPythonMap->SpecialTypeMap->insert(i,
      vtkPythonSpecialTypeMap::value_type(
        classname,
        PyVTKSpecialType(pytype, methods, constructors, copyfunc)));
274
  }
275

276
  return i->second.py_type;
277
278
}

279
//--------------------------------------------------------------------
280
PyVTKSpecialType *vtkPythonUtil::FindSpecialType(const char *classname)
Ken Martin's avatar
Ken Martin committed
281
{
282
  if (vtkPythonMap)
283
  {
284
285
    vtkPythonSpecialTypeMap::iterator it =
      vtkPythonMap->SpecialTypeMap->find(classname);
Ken Martin's avatar
Ken Martin committed
286

287
    if (it != vtkPythonMap->SpecialTypeMap->end())
288
    {
289
      return &it->second;
Ken Martin's avatar
Ken Martin committed
290
    }
291
  }
Ken Martin's avatar
Ken Martin committed
292

293
  return nullptr;
294
}
295

296
//--------------------------------------------------------------------
297
void vtkPythonUtil::AddObjectToMap(PyObject *obj, vtkObjectBase *ptr)
298
{
299
  vtkPythonUtilCreateIfNeeded();
Ken Martin's avatar
Ken Martin committed
300
301

#ifdef VTKPYTHONDEBUG
302
  vtkGenericWarningMacro("Adding an object to map ptr = " << ptr);
303
#endif
304

305
  ((PyVTKObject *)obj)->vtk_ptr = ptr;
306
  vtkPythonMap->ObjectMap->add(ptr, obj);
Ken Martin's avatar
Ken Martin committed
307
308

#ifdef VTKPYTHONDEBUG
309
  vtkGenericWarningMacro("Added object to map obj= " << obj << " "
310
                         << ptr);
311
312
#endif
}
Ken Martin's avatar
Ken Martin committed
313

314
//--------------------------------------------------------------------
315
void vtkPythonUtil::RemoveObjectFromMap(PyObject *obj)
Ken Martin's avatar
Ken Martin committed
316
{
317
  PyVTKObject *pobj = (PyVTKObject *)obj;
318

Ken Martin's avatar
Ken Martin committed
319
#ifdef VTKPYTHONDEBUG
320
321
  vtkGenericWarningMacro("Deleting an object from map obj = "
                         << pobj << " " << pobj->vtk_ptr);
322
#endif
323

324
  if (vtkPythonMap && vtkPythonMap->ObjectMap->count(pobj->vtk_ptr))
325
  {
326
327
328
    vtkWeakPointerBase wptr;

    // check for customized class or dict
329
    if (pobj->vtk_class->py_type != Py_TYPE(pobj) ||
330
        PyDict_Size(pobj->vtk_dict))
331
    {
332
      wptr = pobj->vtk_ptr;
333
    }
334

335
    vtkPythonMap->ObjectMap->remove(pobj->vtk_ptr);
336
337
338

    // if the VTK object still exists, then make a ghost
    if (wptr.GetPointer())
339
    {
340
      // List of attrs to be deleted
341
      std::vector<PyObject*> delList;
342

343
      // Erase ghosts of VTK objects that have been deleted
Ben Boeckel's avatar
Ben Boeckel committed
344
      vtkPythonGhostMap::iterator i =
345
346
        vtkPythonMap->GhostMap->begin();
      while (i != vtkPythonMap->GhostMap->end())
347
      {
348
        if (!i->second.vtk_ptr.GetPointer())
349
        {
350
351
          delList.push_back((PyObject *)i->second.vtk_class);
          delList.push_back(i->second.vtk_dict);
352
          vtkPythonMap->GhostMap->erase(i++);
353
        }
354
        else
355
        {
356
357
          ++i;
        }
358
      }
359
360

      // Add this new ghost to the map
361
362
      PyVTKObjectGhost &g = (*vtkPythonMap->GhostMap)[pobj->vtk_ptr];
      g.vtk_ptr = wptr;
363
      g.vtk_class = Py_TYPE(pobj);
364
365
366
      g.vtk_dict = pobj->vtk_dict;
      Py_INCREF(g.vtk_class);
      Py_INCREF(g.vtk_dict);
367
368
369

      // Delete attrs of erased objects.  Must be done at the end.
      for (size_t j = 0; j < delList.size(); j++)
370
      {
371
        Py_DECREF(delList[j]);
372
      }
Berk Geveci's avatar
Berk Geveci committed
373
    }
374
  }
Ken Martin's avatar
Ken Martin committed
375
376
}

377
//--------------------------------------------------------------------
378
PyObject *vtkPythonUtil::FindObject(vtkObjectBase *ptr)
Ken Martin's avatar
Ken Martin committed
379
{
380
  PyObject *obj = nullptr;
381

382
  if (ptr && vtkPythonMap)
383
  {
Ben Boeckel's avatar
Ben Boeckel committed
384
    vtkPythonObjectMap::iterator i =
385
      vtkPythonMap->ObjectMap->find(ptr);
386
    if (i != vtkPythonMap->ObjectMap->end())
387
    {
388
      obj = i->second.first;
389
    }
390
    if (obj)
391
    {
392
      Py_INCREF(obj);
393
      return obj;
394
    }
395
  }
396
  else
397
  {
398
    Py_INCREF(Py_None);
399
    return Py_None;
400
  }
401
402

  // search weak list for object, resurrect if it is there
Ben Boeckel's avatar
Ben Boeckel committed
403
  vtkPythonGhostMap::iterator j =
404
    vtkPythonMap->GhostMap->find(ptr);
David Gobbi's avatar
David Gobbi committed
405
  if (j != vtkPythonMap->GhostMap->end())
406
  {
David Gobbi's avatar
David Gobbi committed
407
    if (j->second.vtk_ptr.GetPointer())
408
    {
409
410
      obj = PyVTKObject_FromPointer(
        j->second.vtk_class, j->second.vtk_dict, ptr);
411
    }
David Gobbi's avatar
David Gobbi committed
412
413
414
    Py_DECREF(j->second.vtk_class);
    Py_DECREF(j->second.vtk_dict);
    vtkPythonMap->GhostMap->erase(j);
415
  }
416

417
418
419
420
421
422
423
424
  return obj;
}

//--------------------------------------------------------------------
PyObject *vtkPythonUtil::GetObjectFromPointer(vtkObjectBase *ptr)
{
  PyObject *obj = vtkPythonUtil::FindObject(ptr);

425
  if (obj == nullptr)
426
  {
427
    // create a new object
428
    PyVTKClass *vtkclass = nullptr;
Ben Boeckel's avatar
Ben Boeckel committed
429
    vtkPythonClassMap::iterator k =
430
      vtkPythonMap->ClassMap->find(ptr->GetClassName());
David Gobbi's avatar
David Gobbi committed
431
    if (k != vtkPythonMap->ClassMap->end())
432
    {
433
      vtkclass = &k->second;
434
    }
435

436
    // if the class was not in the map, then find the nearest base class
437
    // that is, and associate ptr->GetClassName() with that base class
438
    if (vtkclass == nullptr)
439
    {
440
      const char *classname = ptr->GetClassName();
441
      vtkclass = vtkPythonUtil::FindNearestBaseClass(ptr);
442
443
444
      vtkPythonClassMap::iterator i =
        vtkPythonMap->ClassMap->find(classname);
      if (i == vtkPythonMap->ClassMap->end())
445
      {
446
447
        vtkPythonMap->ClassMap->insert(
          i, vtkPythonClassMap::value_type(classname, *vtkclass));
David Gobbi's avatar
David Gobbi committed
448
      }
449
    }
David Gobbi's avatar
David Gobbi committed
450

451
    obj = PyVTKObject_FromPointer(vtkclass->py_type, nullptr, ptr);
452
  }
David Gobbi's avatar
David Gobbi committed
453

Ken Martin's avatar
Ken Martin committed
454
455
456
  return obj;
}

457
458
459
460
461
462
463
//--------------------------------------------------------------------
const char *vtkPythonUtil::PythonicClassName(const char *classname)
{
  const char *cp = classname;

  /* check for non-alphanumeric chars */
  if (isalpha(*cp) || *cp == '_')
464
  {
465
    do { cp++; } while (isalnum(*cp) || *cp == '_');
466
  }
467
468

  if (*cp != '\0')
469
  {
470
    /* look up class and get its pythonic name */
471
472
    PyTypeObject *pytype = vtkPythonUtil::FindClassTypeObject(classname);
    if (pytype)
473
    {
474
      classname = vtkPythonUtil::StripModule(pytype->tp_name);
475
    }
476
  }
477
478
479
480

  return classname;
}

481
482
483
484
485
//--------------------------------------------------------------------
const char *vtkPythonUtil::StripModule(const char *tpname)
{
  const char *cp = tpname;
  while (*cp != '.' && *cp != '\0')
486
  {
487
    cp++;
488
  }
489
  if (*cp == '.')
490
  {
491
    return ++cp;
492
  }
493
494
495
  return tpname;
}

496
//--------------------------------------------------------------------
497
PyTypeObject *vtkPythonUtil::AddClassToMap(
498
  PyTypeObject *pytype, PyMethodDef *methods,
499
  const char *classname, vtknewfunc constructor)
500
{
501
  vtkPythonUtilCreateIfNeeded();
502
503
504
505

  // lets make sure it isn't already there
  vtkPythonClassMap::iterator i =
    vtkPythonMap->ClassMap->find(classname);
506
  if (i == vtkPythonMap->ClassMap->end())
507
  {
508
509
510
511
    i = vtkPythonMap->ClassMap->insert(i,
      vtkPythonClassMap::value_type(
        classname,
        PyVTKClass(pytype, methods, classname, constructor)));
512
  }
513

514
  return i->second.py_type;
515
516
517
}

//--------------------------------------------------------------------
518
PyVTKClass *vtkPythonUtil::FindClass(const char *classname)
519
520
{
  if (vtkPythonMap)
521
  {
522
523
524
    vtkPythonClassMap::iterator it =
      vtkPythonMap->ClassMap->find(classname);
    if (it != vtkPythonMap->ClassMap->end())
525
    {
526
      return &it->second;
527
    }
528
  }
529

530
  return nullptr;
531
532
533
}

//--------------------------------------------------------------------
534
535
// this is a helper function to find the nearest base class for an
// object whose class is not in the ClassDict
536
PyVTKClass *vtkPythonUtil::FindNearestBaseClass(vtkObjectBase *ptr)
537
{
538
  PyVTKClass *nearestbase = nullptr;
539
  int maxdepth = 0;
540
  int depth;
541

542
  for (vtkPythonClassMap::iterator classes =
543
        vtkPythonMap->ClassMap->begin();
544
       classes != vtkPythonMap->ClassMap->end(); ++classes)
545
  {
546
    PyVTKClass *pyclass = &classes->second;
547

548
    if (ptr->IsA(pyclass->vtk_name))
549
    {
550
      PyTypeObject *base = pyclass->py_type->tp_base;
Kyle Lutz's avatar
Kyle Lutz committed
551
      // count the hierarchy depth for this class
552
      for (depth = 0; base != nullptr; depth++)
553
      {
554
        base = base->tp_base;
555
      }
556
      // we want the class that is furthest from vtkObjectBase
David Gobbi's avatar
David Gobbi committed
557
      if (depth > maxdepth)
558
      {
David Gobbi's avatar
David Gobbi committed
559
560
561
        maxdepth = depth;
        nearestbase = pyclass;
      }
562
    }
563
  }
564

565
566
567
  return nearestbase;
}

568
//--------------------------------------------------------------------
569
570
vtkObjectBase *vtkPythonUtil::GetPointerFromObject(
  PyObject *obj, const char *result_type)
571
{
572
  vtkObjectBase *ptr;
573

574
  // convert Py_None to nullptr every time
575
  if (obj == Py_None)
576
  {
577
    return nullptr;
578
  }
579
580

  // check to ensure it is a vtk object
581
  if (!PyVTKObject_Check(obj))
582
  {
583
    obj = PyObject_GetAttrString(obj, "__vtk__");
584
    if (obj)
585
    {
586
      PyObject *arglist = Py_BuildValue("()");
587
588
589
      PyObject *result = PyEval_CallObject(obj, arglist);
      Py_DECREF(arglist);
      Py_DECREF(obj);
590
      if (result == nullptr)
591
      {
592
        return nullptr;
593
      }
594
      if (!PyVTKObject_Check(result))
595
      {
596
        PyErr_SetString(PyExc_TypeError, "__vtk__() doesn't return a VTK object");
597
        Py_DECREF(result);
598
        return nullptr;
599
      }
600
      else
601
      {
602
603
        ptr = ((PyVTKObject *)result)->vtk_ptr;
        Py_DECREF(result);
604
      }
605
    }
606
    else
607
    {
608
#ifdef VTKPYTHONDEBUG
David Gobbi's avatar
David Gobbi committed
609
      vtkGenericWarningMacro("Object " << obj << " is not a VTK object!!");
610
#endif
611
      PyErr_SetString(PyExc_TypeError, "method requires a VTK object");
612
      return nullptr;
613
    }
614
  }
615
  else
616
  {
617
    ptr = ((PyVTKObject *)obj)->vtk_ptr;
618
  }
619

620
621
#ifdef VTKPYTHONDEBUG
  vtkGenericWarningMacro("Checking into obj " << obj << " ptr = " << ptr);
622
#endif
623

624
  if (ptr->IsA(result_type))
625
  {
Ken Martin's avatar
Ken Martin committed
626
#ifdef VTKPYTHONDEBUG
627
    vtkGenericWarningMacro("Got obj= " << obj << " ptr= " << ptr << " " << result_type);
628
#endif
629
    return ptr;
630
  }
Ken Martin's avatar
Ken Martin committed
631
  else
632
  {
633
    char error_string[2048];
Ken Martin's avatar
Ken Martin committed
634
#ifdef VTKPYTHONDEBUG
David Gobbi's avatar
David Gobbi committed
635
    vtkGenericWarningMacro("vtk bad argument, type conversion failed.");
David Gobbi's avatar
David Gobbi committed
636
#endif
637
638
639
640
    snprintf(error_string, sizeof(error_string), "method requires a %.500s, a %.500s was provided.",
             vtkPythonUtil::PythonicClassName(result_type),
             vtkPythonUtil::PythonicClassName(
               ((vtkObjectBase *)ptr)->GetClassName()));
641
    PyErr_SetString(PyExc_TypeError, error_string);
642
    return nullptr;
643
  }
Ken Martin's avatar
Ken Martin committed
644
645
}

646
647
648
649
650
//----------------
// union of long int and pointer
union vtkPythonUtilPointerUnion
{
  void *p;
651
  uintptr_t l;
652
653
654
655
656
657
658
};

//----------------
// union of long int and pointer
union vtkPythonUtilConstPointerUnion
{
  const void *p;
659
  uintptr_t l;
660
661
};

662
663
664
//--------------------------------------------------------------------
PyObject *vtkPythonUtil::GetObjectFromObject(
  PyObject *arg, const char *type)
665
{
666
  union vtkPythonUtilPointerUnion u;
667
  PyObject *tmp = nullptr;
668
669
670

#ifdef Py_USING_UNICODE
  if (PyUnicode_Check(arg))
671
  {
672
673
    tmp = PyUnicode_AsUTF8String(arg);
    arg = tmp;
674
  }
675
#endif
676

677
  if (PyBytes_Check(arg))
678
  {
679
    vtkObjectBase *ptr;
680
    char *ptrText = PyBytes_AsString(arg);
David Gobbi's avatar
David Gobbi committed
681

682
    char typeCheck[1024];  // typeCheck is currently not used
683
684
685
    unsigned long long l;
    int i = sscanf(ptrText,"_%llx_%s", &l, typeCheck);
    u.l = static_cast<uintptr_t>(l);
686

David Gobbi's avatar
David Gobbi committed
687
    if (i <= 0)
688
    {
689
690
      i = sscanf(ptrText,"Addr=0x%llx", &l);
      u.l = static_cast<uintptr_t>(l);
691
    }
David Gobbi's avatar
David Gobbi committed
692
    if (i <= 0)
693
    {
694
      i = sscanf(ptrText, "%p", &u.p);
695
    }
David Gobbi's avatar
David Gobbi committed
696
    if (i <= 0)
697
    {
698
      Py_XDECREF(tmp);
Kunda's avatar
Kunda committed
699
      PyErr_SetString(PyExc_ValueError, "could not extract hexadecimal address from argument string");
700
      return nullptr;
701
    }
David Gobbi's avatar
David Gobbi committed
702

703
704
    ptr = static_cast<vtkObjectBase *>(u.p);

David Gobbi's avatar
David Gobbi committed
705
    if (!ptr->IsA(type))
706
    {
707
      char error_string[2048];
708
      snprintf(error_string,sizeof(error_string),"method requires a %.500s address, a %.500s address was provided.",
709
              type, ptr->GetClassName());
710
      Py_XDECREF(tmp);
711
      PyErr_SetString(PyExc_TypeError, error_string);
712
      return nullptr;
713
    }
714

715
    Py_XDECREF(tmp);
716
    return vtkPythonUtil::GetObjectFromPointer(ptr);
717
  }
718

719
  Py_XDECREF(tmp);
720
  PyErr_SetString(PyExc_TypeError, "method requires a string argument");
721
  return nullptr;
722
723
}

724
//--------------------------------------------------------------------
725
void *vtkPythonUtil::GetPointerFromSpecialObject(
726
  PyObject *obj, const char *result_type, PyObject **newobj)
727
{
728
  if (vtkPythonMap == nullptr)
729
  {
730
    PyErr_SetString(PyExc_TypeError, "method requires a vtkPythonMap");
731
    return nullptr;
732
  }