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