1 /* ----------------------------------------------------------------------------- 2 * director.swg 3 * 4 * This file contains support for director classes that proxy 5 * method calls from C++ to Python extensions. 6 * ----------------------------------------------------------------------------- */ 7 8 #ifndef SWIG_DIRECTOR_PYTHON_HEADER_ 9 #define SWIG_DIRECTOR_PYTHON_HEADER_ 10 11 #ifdef __cplusplus 12 13 #include <string> 14 #include <iostream> 15 #include <exception> 16 #include <vector> 17 #include <map> 18 19 20 /* 21 Use -DSWIG_PYTHON_DIRECTOR_NO_VTABLE if you don't want to generate a 'virtual 22 table', and avoid multiple GetAttr calls to retrieve the python 23 methods. 24 */ 25 26 #ifndef SWIG_PYTHON_DIRECTOR_NO_VTABLE 27 #ifndef SWIG_PYTHON_DIRECTOR_VTABLE 28 #define SWIG_PYTHON_DIRECTOR_VTABLE 29 #endif 30 #endif 31 32 33 34 /* 35 Use -DSWIG_DIRECTOR_NO_UEH if you prefer to avoid the use of the 36 Undefined Exception Handler provided by swig. 37 */ 38 #ifndef SWIG_DIRECTOR_NO_UEH 39 #ifndef SWIG_DIRECTOR_UEH 40 #define SWIG_DIRECTOR_UEH 41 #endif 42 #endif 43 44 45 /* 46 Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the 47 'Swig' namespace. This could be useful for multi-modules projects. 48 */ 49 #ifdef SWIG_DIRECTOR_STATIC 50 /* Force anonymous (static) namespace */ 51 #define Swig 52 #endif 53 54 55 /* 56 Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the 57 native C++ RTTI and dynamic_cast<>. But be aware that directors 58 could stop working when using this option. 59 */ 60 #ifdef SWIG_DIRECTOR_NORTTI 61 /* 62 When we don't use the native C++ RTTI, we implement a minimal one 63 only for Directors. 64 */ 65 # ifndef SWIG_DIRECTOR_RTDIR 66 # define SWIG_DIRECTOR_RTDIR 67 #include <map> 68 69 namespace Swig { 70 class Director; 71 SWIGINTERN std::map<void*,Director*>& get_rtdir_map() { 72 static std::map<void*,Director*> rtdir_map; 73 return rtdir_map; 74 } 75 76 SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) { 77 get_rtdir_map()[vptr] = rtdir; 78 } 79 80 SWIGINTERNINLINE Director *get_rtdir(void *vptr) { 81 std::map<void*,Director*>::const_iterator pos = get_rtdir_map().find(vptr); 82 Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0; 83 return rtdir; 84 } 85 } 86 # endif /* SWIG_DIRECTOR_RTDIR */ 87 88 # define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast<void*>(ARG)) 89 # define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast<void*>(ARG1), ARG2) 90 91 #else 92 93 # define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG) 94 # define SWIG_DIRECTOR_RGTR(ARG1, ARG2) 95 96 #endif /* SWIG_DIRECTOR_NORTTI */ 97 98 extern "C" { 99 struct swig_type_info; 100 } 101 102 namespace Swig { 103 104 /* memory handler */ 105 struct GCItem 106 { 107 virtual ~GCItem() {} 108 109 virtual int get_own() const 110 { 111 return 0; 112 } 113 }; 114 115 struct GCItem_var 116 { 117 GCItem_var(GCItem *item = 0) : _item(item) 118 { 119 } 120 121 GCItem_var& operator=(GCItem *item) 122 { 123 GCItem *tmp = _item; 124 _item = item; 125 delete tmp; 126 return *this; 127 } 128 129 ~GCItem_var() 130 { 131 delete _item; 132 } 133 134 GCItem * operator->() const 135 { 136 return _item; 137 } 138 139 private: 140 GCItem *_item; 141 }; 142 143 struct GCItem_Object : GCItem 144 { 145 GCItem_Object(int own) : _own(own) 146 { 147 } 148 149 virtual ~GCItem_Object() 150 { 151 } 152 153 int get_own() const 154 { 155 return _own; 156 } 157 158 private: 159 int _own; 160 }; 161 162 template <typename Type> 163 struct GCItem_T : GCItem 164 { 165 GCItem_T(Type *ptr) : _ptr(ptr) 166 { 167 } 168 169 virtual ~GCItem_T() 170 { 171 delete _ptr; 172 } 173 174 private: 175 Type *_ptr; 176 }; 177 178 template <typename Type> 179 struct GCArray_T : GCItem 180 { 181 GCArray_T(Type *ptr) : _ptr(ptr) 182 { 183 } 184 185 virtual ~GCArray_T() 186 { 187 delete[] _ptr; 188 } 189 190 private: 191 Type *_ptr; 192 }; 193 194 /* base class for director exceptions */ 195 class DirectorException { 196 protected: 197 std::string swig_msg; 198 public: 199 DirectorException(PyObject *error, const char* hdr ="", const char* msg ="") 200 : swig_msg(hdr) 201 { 202 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 203 if (strlen(msg)) { 204 swig_msg += " "; 205 swig_msg += msg; 206 } 207 if (!PyErr_Occurred()) { 208 PyErr_SetString(error, getMessage()); 209 } 210 SWIG_PYTHON_THREAD_END_BLOCK; 211 } 212 213 const char *getMessage() const 214 { 215 return swig_msg.c_str(); 216 } 217 218 static void raise(PyObject *error, const char *msg) 219 { 220 throw DirectorException(error, msg); 221 } 222 223 static void raise(const char *msg) 224 { 225 raise(PyExc_RuntimeError, msg); 226 } 227 }; 228 229 /* unknown exception handler */ 230 class UnknownExceptionHandler 231 { 232 #ifdef SWIG_DIRECTOR_UEH 233 static void handler() { 234 try { 235 throw; 236 } catch (DirectorException& e) { 237 std::cerr << "SWIG Director exception caught:" << std::endl 238 << e.getMessage() << std::endl; 239 } catch (std::exception& e) { 240 std::cerr << "std::exception caught: "<< e.what() << std::endl; 241 } catch (...) { 242 std::cerr << "Unknown exception caught." << std::endl; 243 } 244 245 std::cerr << std::endl 246 << "Python interpreter traceback:" << std::endl; 247 PyErr_Print(); 248 std::cerr << std::endl; 249 250 std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl 251 << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl 252 << std::endl 253 << "Exception is being re-thrown, program will likely abort/terminate." << std::endl; 254 throw; 255 } 256 257 public: 258 259 std::unexpected_handler old; 260 UnknownExceptionHandler(std::unexpected_handler nh = handler) 261 { 262 old = std::set_unexpected(nh); 263 } 264 265 ~UnknownExceptionHandler() 266 { 267 std::set_unexpected(old); 268 } 269 #endif 270 }; 271 272 /* type mismatch in the return value from a python method call */ 273 class DirectorTypeMismatchException : public Swig::DirectorException { 274 public: 275 DirectorTypeMismatchException(PyObject *error, const char* msg="") 276 : Swig::DirectorException(error, "SWIG director type mismatch", msg) 277 { 278 } 279 280 DirectorTypeMismatchException(const char* msg="") 281 : Swig::DirectorException(PyExc_TypeError, "SWIG director type mismatch", msg) 282 { 283 } 284 285 static void raise(PyObject *error, const char *msg) 286 { 287 throw DirectorTypeMismatchException(error, msg); 288 } 289 290 static void raise(const char *msg) 291 { 292 throw DirectorTypeMismatchException(msg); 293 } 294 }; 295 296 /* any python exception that occurs during a director method call */ 297 class DirectorMethodException : public Swig::DirectorException { 298 public: 299 DirectorMethodException(const char* msg = "") 300 : DirectorException(PyExc_RuntimeError, "SWIG director method error.", msg) 301 { 302 } 303 304 static void raise(const char *msg) 305 { 306 throw DirectorMethodException(msg); 307 } 308 }; 309 310 /* attempt to call a pure virtual method via a director method */ 311 class DirectorPureVirtualException : public Swig::DirectorException 312 { 313 public: 314 DirectorPureVirtualException(const char* msg = "") 315 : DirectorException(PyExc_RuntimeError, "SWIG director pure virtual method called", msg) 316 { 317 } 318 319 static void raise(const char *msg) 320 { 321 throw DirectorPureVirtualException(msg); 322 } 323 }; 324 325 326 #if defined(SWIG_PYTHON_THREADS) 327 /* __THREAD__ is the old macro to activate some thread support */ 328 # if !defined(__THREAD__) 329 # define __THREAD__ 1 330 # endif 331 #endif 332 333 #ifdef __THREAD__ 334 # include "pythread.h" 335 class Guard 336 { 337 PyThread_type_lock & mutex_; 338 339 public: 340 Guard(PyThread_type_lock & mutex) : mutex_(mutex) 341 { 342 PyThread_acquire_lock(mutex_, WAIT_LOCK); 343 } 344 345 ~Guard() 346 { 347 PyThread_release_lock(mutex_); 348 } 349 }; 350 # define SWIG_GUARD(mutex) Guard _guard(mutex) 351 #else 352 # define SWIG_GUARD(mutex) 353 #endif 354 355 /* director base class */ 356 class Director { 357 private: 358 /* pointer to the wrapped python object */ 359 PyObject* swig_self; 360 /* flag indicating whether the object is owned by python or c++ */ 361 mutable bool swig_disown_flag; 362 363 /* decrement the reference count of the wrapped python object */ 364 void swig_decref() const { 365 if (swig_disown_flag) { 366 SWIG_PYTHON_THREAD_BEGIN_BLOCK; 367 Py_DECREF(swig_self); 368 SWIG_PYTHON_THREAD_END_BLOCK; 369 } 370 } 371 372 public: 373 /* wrap a python object, optionally taking ownership */ 374 Director(PyObject* self) : swig_self(self), swig_disown_flag(false) { 375 swig_incref(); 376 } 377 378 379 /* discard our reference at destruction */ 380 virtual ~Director() { 381 swig_decref(); 382 } 383 384 385 /* return a pointer to the wrapped python object */ 386 PyObject *swig_get_self() const { 387 return swig_self; 388 } 389 390 /* acquire ownership of the wrapped python object (the sense of "disown" 391 * is from python) */ 392 void swig_disown() const { 393 if (!swig_disown_flag) { 394 swig_disown_flag=true; 395 swig_incref(); 396 } 397 } 398 399 /* increase the reference count of the wrapped python object */ 400 void swig_incref() const { 401 if (swig_disown_flag) { 402 Py_INCREF(swig_self); 403 } 404 } 405 406 /* methods to implement pseudo protected director members */ 407 virtual bool swig_get_inner(const char* /* swig_protected_method_name */) const { 408 return true; 409 } 410 411 virtual void swig_set_inner(const char* /* swig_protected_method_name */, bool /* swig_val */) const { 412 } 413 414 /* ownership management */ 415 private: 416 typedef std::map<void*, GCItem_var> swig_ownership_map; 417 mutable swig_ownership_map swig_owner; 418 #ifdef __THREAD__ 419 static PyThread_type_lock swig_mutex_own; 420 #endif 421 422 public: 423 template <typename Type> 424 void swig_acquire_ownership_array(Type *vptr) const 425 { 426 if (vptr) { 427 SWIG_GUARD(swig_mutex_own); 428 swig_owner[vptr] = new GCArray_T<Type>(vptr); 429 } 430 } 431 432 template <typename Type> 433 void swig_acquire_ownership(Type *vptr) const 434 { 435 if (vptr) { 436 SWIG_GUARD(swig_mutex_own); 437 swig_owner[vptr] = new GCItem_T<Type>(vptr); 438 } 439 } 440 441 void swig_acquire_ownership_obj(void *vptr, int own) const 442 { 443 if (vptr && own) { 444 SWIG_GUARD(swig_mutex_own); 445 swig_owner[vptr] = new GCItem_Object(own); 446 } 447 } 448 449 int swig_release_ownership(void *vptr) const 450 { 451 int own = 0; 452 if (vptr) { 453 SWIG_GUARD(swig_mutex_own); 454 swig_ownership_map::iterator iter = swig_owner.find(vptr); 455 if (iter != swig_owner.end()) { 456 own = iter->second->get_own(); 457 swig_owner.erase(iter); 458 } 459 } 460 return own; 461 } 462 463 template <typename Type> 464 static PyObject* swig_pyobj_disown(PyObject *pyobj, PyObject *SWIGUNUSEDPARM(args)) 465 { 466 SwigPyObject *sobj = (SwigPyObject *)pyobj; 467 sobj->own = 0; 468 Director *d = SWIG_DIRECTOR_CAST(reinterpret_cast<Type *>(sobj->ptr)); 469 if (d) 470 d->swig_disown(); 471 return PyWeakref_NewProxy(pyobj, NULL); 472 } 473 474 }; 475 476 #ifdef __THREAD__ 477 PyThread_type_lock Director::swig_mutex_own = PyThread_allocate_lock(); 478 #endif 479 } 480 481 #endif /* __cplusplus */ 482 483 484 #endif 485