/* ----------------------------------------------------------------------------- * director.swg * * This file contains support for director classes so that Perl proxy * methods can be called from C++. * ----------------------------------------------------------------------------- */ #ifndef SWIG_DIRECTOR_PERL_HEADER_ #define SWIG_DIRECTOR_PERL_HEADER_ #include #include #include #include #include /* 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 namespace Swig { class Director; SWIGINTERN std::map& get_rtdir_map() { static std::map 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::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(ARG)) # define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast(ARG1), ARG2) #else # define SWIG_DIRECTOR_CAST(ARG) dynamic_cast(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 struct GCItem_T : GCItem { GCItem_T(Type *ptr) : _ptr(ptr) { } virtual ~GCItem_T() { delete _ptr; } private: Type *_ptr; }; template 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 std::exception { public: virtual SV *getNative() const = 0; }; /* exceptions emitted by Perl */ class DirectorMethodException : public DirectorException { protected: SV *err; public: DirectorMethodException(SV *sv = sv_mortalcopy(ERRSV)) : err(sv) { SvREFCNT_inc(err); } const char *what() const throw() { 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 DirectorException { protected: std::string msg; DirectorWrapException(const char *str) : msg(str) { } public: virtual ~DirectorWrapException() throw() { } const char *what() const throw() { return msg.c_str(); } virtual SV *getNative() const { return sv_2mortal(newSVpvn(msg.data(), msg.size())); } }; class DirectorTypeMismatchException : public 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 DirectorWrapException { public: DirectorPureVirtualException(const char *name) : DirectorWrapException("SWIG director pure virtual method called: ") { msg += name; } static void raise(const char *name) { throw DirectorPureVirtualException(name); } }; /* 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 Perl object. */ 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()); } /* discard our reference at destruction */ virtual ~Director() { swig_decref(); } /* return a pointer to the wrapped Perl 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 Perl object (the sense of "disown" is from perl) */ void swig_disown() const { if (!swig_disown_flag) { swig_disown_flag=true; swig_incref(); } } /* increase the reference count of the wrapped Perl 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 swig_ownership_map; mutable swig_ownership_map swig_owner; public: template void swig_acquire_ownership_array(Type *vptr) const { if (vptr) { swig_owner[vptr] = new GCArray_T(vptr); } } template void swig_acquire_ownership(Type *vptr) const { if (vptr) { swig_owner[vptr] = new GCItem_T(vptr); } } void swig_acquire_ownership_obj(void *vptr, int own) const { if (vptr && own) { swig_owner[vptr] = new GCItem_Object(own); } } int swig_release_ownership(void *vptr) const { int own = 0; if (vptr) { 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; } }; } #endif