diff options
author | Robert Stone <talby@trap.mtview.ca.us> | 2013-11-12 12:48:21 -0800 |
---|---|---|
committer | Robert Stone <talby@trap.mtview.ca.us> | 2013-11-12 12:48:21 -0800 |
commit | 34c374d7ae201a2a9902f721e4e31a2ad785b557 (patch) | |
tree | 738fe6e107ea0a57359ecf7a1d4149a877e0d682 /Lib/perl5 | |
parent | 0901a3e867a733cbede8b034f92c964025c38c8a (diff) | |
download | swig-34c374d7ae201a2a9902f721e4e31a2ad785b557.tar.gz |
don't forget the most important part
Diffstat (limited to 'Lib/perl5')
-rw-r--r-- | Lib/perl5/director.swg | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/Lib/perl5/director.swg b/Lib/perl5/director.swg new file mode 100644 index 000000000..937b727a4 --- /dev/null +++ b/Lib/perl5/director.swg @@ -0,0 +1,479 @@ +/* ----------------------------------------------------------------------------- + * director.swg + * + * This file contains support for director classes that proxy + * method calls from C++ to Python extensions. + * ----------------------------------------------------------------------------- */ + +#ifndef SWIG_DIRECTOR_PERL_HEADER_ +#define SWIG_DIRECTOR_PERL_HEADER_ + +#ifdef __cplusplus + +#include <string> +#include <iostream> +#include <exception> +#include <vector> +#include <map> + + +/* + Use -DSWIG_PYTHON_DIRECTOR_NO_VTABLE if you don't want to generate a 'virtual + table', and avoid multiple GetAttr calls to retrieve the python + methods. +*/ + +#ifndef SWIG_PERL_DIRECTOR_NO_VTABLE +#ifndef SWIG_PERL_DIRECTOR_VTABLE +#define SWIG_PERL_DIRECTOR_VTABLE +#endif +#endif + + + +/* + Use -DSWIG_DIRECTOR_NO_UEH if you prefer to avoid the use of the + Undefined Exception Handler provided by swig. +*/ +#ifndef SWIG_DIRECTOR_NO_UEH +#ifndef SWIG_DIRECTOR_UEH +#define SWIG_DIRECTOR_UEH +#endif +#endif + + +/* + Use -DSWIG_DIRECTOR_STATIC if you prefer to avoid the use of the + 'Swig' namespace. This could be useful for multi-modules projects. +*/ +#ifdef SWIG_DIRECTOR_STATIC +/* Force anonymous (static) namespace */ +#define Swig +#endif + + +/* + Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the + native C++ RTTI and dynamic_cast<>. But be aware that directors + could stop working when using this option. +*/ +#ifdef SWIG_DIRECTOR_NORTTI +/* + When we don't use the native C++ RTTI, we implement a minimal one + only for Directors. +*/ +# ifndef SWIG_DIRECTOR_RTDIR +# define SWIG_DIRECTOR_RTDIR +#include <map> + +namespace Swig { + class Director; + SWIGINTERN std::map<void*,Director*>& get_rtdir_map() { + static std::map<void*,Director*> rtdir_map; + return rtdir_map; + } + + SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) { + get_rtdir_map()[vptr] = rtdir; + } + + SWIGINTERNINLINE Director *get_rtdir(void *vptr) { + std::map<void*,Director*>::const_iterator pos = get_rtdir_map().find(vptr); + Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0; + return rtdir; + } +} +# endif /* SWIG_DIRECTOR_RTDIR */ + +# define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast<void*>(ARG)) +# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast<void*>(ARG1), ARG2) + +#else + +# define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG) +# define SWIG_DIRECTOR_RGTR(ARG1, ARG2) + +#endif /* SWIG_DIRECTOR_NORTTI */ + +extern "C" { + struct swig_type_info; +} + +namespace Swig { + + /* memory handler */ + struct GCItem + { + virtual ~GCItem() {} + + virtual int get_own() const + { + return 0; + } + }; + + struct GCItem_var + { + GCItem_var(GCItem *item = 0) : _item(item) + { + } + + GCItem_var& operator=(GCItem *item) + { + GCItem *tmp = _item; + _item = item; + delete tmp; + return *this; + } + + ~GCItem_var() + { + delete _item; + } + + GCItem * operator->() const + { + return _item; + } + + private: + GCItem *_item; + }; + + struct GCItem_Object : GCItem + { + GCItem_Object(int own) : _own(own) + { + } + + virtual ~GCItem_Object() + { + } + + int get_own() const + { + return _own; + } + + private: + int _own; + }; + + template <typename Type> + struct GCItem_T : GCItem + { + GCItem_T(Type *ptr) : _ptr(ptr) + { + } + + virtual ~GCItem_T() + { + delete _ptr; + } + + private: + Type *_ptr; + }; + + template <typename Type> + struct GCArray_T : GCItem + { + GCArray_T(Type *ptr) : _ptr(ptr) + { + } + + virtual ~GCArray_T() + { + delete[] _ptr; + } + + private: + Type *_ptr; + }; + + /* base class for director exceptions */ + class DirectorException { + public: + virtual const char *getMessage() const = 0; + virtual SV *getNative() const = 0; + }; + /* exceptions emitted by Perl */ + class DirectorMethodException : public Swig::DirectorException { + protected: + SV *err; + public: + DirectorMethodException(SV *sv) + : err(sv) + { + SvREFCNT_inc(err); + } + ~DirectorMethodException() + { + SvREFCNT_dec(err); + } + const char *getMessage() const + { + return SvPV_nolen(err); + } + SV *getNative() const + { + return sv_2mortal(newSVsv(err)); + } + static void raise(SV *sv) + { + throw DirectorMethodException(sv); + } + }; + /* exceptions emitted by wrap code */ + class DirectorWrapException : public Swig::DirectorException { + protected: + std::string msg; + DirectorWrapException(const char *str) + : msg(str) + { + } + public: + virtual const char *getMessage() const + { + return msg.c_str(); + } + virtual SV *getNative() const { + return sv_2mortal(newSVpvn(msg.data(), msg.size())); + } + }; + class DirectorTypeMismatchException : public Swig::DirectorWrapException { + public: + DirectorTypeMismatchException(const char *str) + : DirectorWrapException(str) + { + } + static void raise(const char *type, const char *msg) + { + std::string err = std::string(type); + err += ": "; + err += msg; + throw DirectorTypeMismatchException(err.c_str()); + } + }; + class DirectorPureVirtualException : public Swig::DirectorWrapException { + public: + DirectorPureVirtualException(const char *name) + : DirectorWrapException("SWIG director pure virtual method called: ") + { + msg += name; + } + static void raise(const char *name) + { + throw DirectorPureVirtualException(name); + } + }; +// /* unknown exception handler */ +// class UnknownExceptionHandler +// { +//#ifdef SWIG_DIRECTOR_UEH +// static void handler() { +// try { +// throw; +// } catch (DirectorException& e) { +// std::cerr << "SWIG Director exception caught:" << std::endl +// << e.getMessage() << std::endl; +// } catch (std::exception& e) { +// std::cerr << "std::exception caught: "<< e.what() << std::endl; +// } catch (...) { +// std::cerr << "Unknown exception caught." << std::endl; +// } +// +// //std::cerr << std::endl +// // << "Python interpreter traceback:" << std::endl; +// //PyErr_Print(); +// //std::cerr << std::endl; +// +// std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl +// << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl +// << std::endl +// << "Exception is being re-thrown, program will likely abort/terminate." << std::endl; +// throw; +// } +// +// public: +// +// std::unexpected_handler old; +// UnknownExceptionHandler(std::unexpected_handler nh = handler) +// { +// old = std::set_unexpected(nh); +// } +// +// ~UnknownExceptionHandler() +// { +// std::set_unexpected(old); +// } +//#endif +// }; + +#if defined(SWIG_PYTHON_THREADS) +/* __THREAD__ is the old macro to activate some thread support */ +# if !defined(__THREAD__) +# define __THREAD__ 1 +# endif +#endif + +#ifdef __THREAD__ +# include "pythread.h" + class Guard + { + PyThread_type_lock & mutex_; + + public: + Guard(PyThread_type_lock & mutex) : mutex_(mutex) + { + PyThread_acquire_lock(mutex_, WAIT_LOCK); + } + + ~Guard() + { + PyThread_release_lock(mutex_); + } + }; +# define SWIG_GUARD(mutex) Guard _guard(mutex) +#else +# define SWIG_GUARD(mutex) +#endif + + /* director base class */ + class Director { + private: + /* pointer to the wrapped perl object */ + SV *swig_self; + /* class of wrapped perl object */ + std::string swig_class; + /* flag indicating whether the object is owned by perl or c++ */ + mutable bool swig_disown_flag; + + /* decrement the reference count of the wrapped perl object */ + void swig_decref() const { + if (swig_disown_flag) { + SvREFCNT_dec(swig_self); + } + } + + public: + /* wrap a python object, optionally taking ownership */ + Director(SV *pkg) : swig_disown_flag(false) { + STRLEN len; + char *str = SvPV(pkg, len); + swig_class = std::string(str, len); + swig_self = newRV_inc((SV *)newHV()); + swig_incref(); + } + + + /* discard our reference at destruction */ + virtual ~Director() { + swig_decref(); + } + + + /* return a pointer to the wrapped python object */ + SV *swig_get_self() const { + return swig_self; + } + + const char *swig_get_class() const { + return swig_class.c_str(); + } + + /* acquire ownership of the wrapped python object (the sense of "disown" + * is from python) */ + void swig_disown() const { + if (!swig_disown_flag) { + swig_disown_flag=true; + swig_incref(); + } + } + + /* increase the reference count of the wrapped python object */ + void swig_incref() const { + if (swig_disown_flag) { + SvREFCNT_inc(swig_self); + } + } + + /* methods to implement pseudo protected director members */ + virtual bool swig_get_inner(const char* /* swig_protected_method_name */) const { + return true; + } + + virtual void swig_set_inner(const char* /* swig_protected_method_name */, bool /* swig_val */) const { + } + + /* ownership management */ + private: + typedef std::map<void*, GCItem_var> swig_ownership_map; + mutable swig_ownership_map swig_owner; +#ifdef __THREAD__ + static PyThread_type_lock swig_mutex_own; +#endif + + public: + template <typename Type> + void swig_acquire_ownership_array(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + swig_owner[vptr] = new GCArray_T<Type>(vptr); + } + } + + template <typename Type> + void swig_acquire_ownership(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + swig_owner[vptr] = new GCItem_T<Type>(vptr); + } + } + + void swig_acquire_ownership_obj(void *vptr, int own) const + { + if (vptr && own) { + SWIG_GUARD(swig_mutex_own); + swig_owner[vptr] = new GCItem_Object(own); + } + } + + int swig_release_ownership(void *vptr) const + { + int own = 0; + if (vptr) { + SWIG_GUARD(swig_mutex_own); + swig_ownership_map::iterator iter = swig_owner.find(vptr); + if (iter != swig_owner.end()) { + own = iter->second->get_own(); + swig_owner.erase(iter); + } + } + return own; + } + + //template <typename Type> + //static PyObject* swig_pyobj_disown(PyObject *pyobj, PyObject *SWIGUNUSEDPARM(args)) + //{ + // SwigPyObject *sobj = (SwigPyObject *)pyobj; + // sobj->own = 0; + // Director *d = SWIG_DIRECTOR_CAST(reinterpret_cast<Type *>(sobj->ptr)); + // if (d) + // d->swig_disown(); + // return PyWeakref_NewProxy(pyobj, NULL); + //} + + }; + +#ifdef __THREAD__ + PyThread_type_lock Director::swig_mutex_own = PyThread_allocate_lock(); +#endif +} + +#endif /* __cplusplus */ + + +#endif |