director.swg 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* -----------------------------------------------------------------------------
  2. * director.swg
  3. *
  4. * This file contains support for director classes so that Perl proxy
  5. * methods can be called from C++.
  6. * ----------------------------------------------------------------------------- */
  7. #ifndef SWIG_DIRECTOR_PERL_HEADER_
  8. #define SWIG_DIRECTOR_PERL_HEADER_
  9. #include <string>
  10. #include <iostream>
  11. #include <exception>
  12. #include <vector>
  13. #include <map>
  14. /*
  15. Use -DSWIG_DIRECTOR_NORTTI if you prefer to avoid the use of the
  16. native C++ RTTI and dynamic_cast<>. But be aware that directors
  17. could stop working when using this option.
  18. */
  19. #ifdef SWIG_DIRECTOR_NORTTI
  20. /*
  21. When we don't use the native C++ RTTI, we implement a minimal one
  22. only for Directors.
  23. */
  24. # ifndef SWIG_DIRECTOR_RTDIR
  25. # define SWIG_DIRECTOR_RTDIR
  26. namespace Swig {
  27. class Director;
  28. SWIGINTERN std::map<void *, Director *>& get_rtdir_map() {
  29. static std::map<void *, Director *> rtdir_map;
  30. return rtdir_map;
  31. }
  32. SWIGINTERNINLINE void set_rtdir(void *vptr, Director *rtdir) {
  33. get_rtdir_map()[vptr] = rtdir;
  34. }
  35. SWIGINTERNINLINE Director *get_rtdir(void *vptr) {
  36. std::map<void *, Director *>::const_iterator pos = get_rtdir_map().find(vptr);
  37. Director *rtdir = (pos != get_rtdir_map().end()) ? pos->second : 0;
  38. return rtdir;
  39. }
  40. }
  41. # endif /* SWIG_DIRECTOR_RTDIR */
  42. # define SWIG_DIRECTOR_CAST(ARG) Swig::get_rtdir(static_cast<void *>(ARG))
  43. # define SWIG_DIRECTOR_RGTR(ARG1, ARG2) Swig::set_rtdir(static_cast<void *>(ARG1), ARG2)
  44. #else
  45. # define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG)
  46. # define SWIG_DIRECTOR_RGTR(ARG1, ARG2)
  47. #endif /* SWIG_DIRECTOR_NORTTI */
  48. extern "C" {
  49. struct swig_type_info;
  50. }
  51. namespace Swig {
  52. /* memory handler */
  53. struct GCItem {
  54. virtual ~GCItem() {}
  55. virtual int get_own() const {
  56. return 0;
  57. }
  58. };
  59. struct GCItem_var {
  60. GCItem_var(GCItem *item = 0) : _item(item) {
  61. }
  62. GCItem_var& operator=(GCItem *item) {
  63. GCItem *tmp = _item;
  64. _item = item;
  65. delete tmp;
  66. return *this;
  67. }
  68. ~GCItem_var() {
  69. delete _item;
  70. }
  71. GCItem *operator->() const {
  72. return _item;
  73. }
  74. private:
  75. GCItem *_item;
  76. };
  77. struct GCItem_Object : GCItem {
  78. GCItem_Object(int own) : _own(own) {
  79. }
  80. virtual ~GCItem_Object() {
  81. }
  82. int get_own() const {
  83. return _own;
  84. }
  85. private:
  86. int _own;
  87. };
  88. template <typename Type>
  89. struct GCItem_T : GCItem {
  90. GCItem_T(Type *ptr) : _ptr(ptr) {
  91. }
  92. virtual ~GCItem_T() {
  93. delete _ptr;
  94. }
  95. private:
  96. Type *_ptr;
  97. };
  98. template <typename Type>
  99. struct GCArray_T : GCItem {
  100. GCArray_T(Type *ptr) : _ptr(ptr) {
  101. }
  102. virtual ~GCArray_T() {
  103. delete[] _ptr;
  104. }
  105. private:
  106. Type *_ptr;
  107. };
  108. /* base class for director exceptions */
  109. class DirectorException : public std::exception {
  110. public:
  111. virtual SV *getNative() const = 0;
  112. };
  113. /* exceptions emitted by Perl */
  114. class DirectorMethodException : public DirectorException {
  115. protected:
  116. SV *err;
  117. public:
  118. DirectorMethodException(SV *sv = sv_mortalcopy(ERRSV)) : err(sv) {
  119. SvREFCNT_inc(err);
  120. }
  121. const char *what() const throw() {
  122. return SvPV_nolen(err);
  123. }
  124. SV *getNative() const {
  125. return sv_2mortal(newSVsv(err));
  126. }
  127. static void raise(SV *sv) {
  128. throw DirectorMethodException(sv);
  129. }
  130. };
  131. /* exceptions emitted by wrap code */
  132. class DirectorWrapException : public DirectorException {
  133. protected:
  134. std::string msg;
  135. DirectorWrapException(const char *str) : msg(str) {
  136. }
  137. public:
  138. virtual ~DirectorWrapException() throw() {
  139. }
  140. const char *what() const throw() {
  141. return msg.c_str();
  142. }
  143. virtual SV *getNative() const {
  144. return sv_2mortal(newSVpvn(msg.data(), msg.size()));
  145. }
  146. };
  147. class DirectorTypeMismatchException : public DirectorWrapException {
  148. public:
  149. DirectorTypeMismatchException(const char *str) : DirectorWrapException(str) {
  150. }
  151. static void raise(const char *type, const char *msg) {
  152. std::string err = std::string(type);
  153. err += ": ";
  154. err += msg;
  155. throw DirectorTypeMismatchException(err.c_str());
  156. }
  157. };
  158. class DirectorPureVirtualException : public DirectorWrapException {
  159. public:
  160. DirectorPureVirtualException(const char *name)
  161. : DirectorWrapException("SWIG director pure virtual method called: ") {
  162. msg += name;
  163. }
  164. static void raise(const char *name) {
  165. throw DirectorPureVirtualException(name);
  166. }
  167. };
  168. /* director base class */
  169. class Director {
  170. private:
  171. /* pointer to the wrapped perl object */
  172. SV *swig_self;
  173. /* class of wrapped perl object */
  174. std::string swig_class;
  175. /* flag indicating whether the object is owned by perl or c++ */
  176. mutable bool swig_disown_flag;
  177. /* decrement the reference count of the wrapped perl object */
  178. void swig_decref() const {
  179. if (swig_disown_flag) {
  180. SvREFCNT_dec(swig_self);
  181. }
  182. }
  183. public:
  184. /* wrap a Perl object. */
  185. Director(SV *pkg) : swig_disown_flag(false) {
  186. STRLEN len;
  187. char *str = SvPV(pkg, len);
  188. swig_class = std::string(str, len);
  189. swig_self = newRV_inc((SV *)newHV());
  190. }
  191. /* discard our reference at destruction */
  192. virtual ~Director() {
  193. swig_decref();
  194. }
  195. /* return a pointer to the wrapped Perl object */
  196. SV *swig_get_self() const {
  197. return swig_self;
  198. }
  199. const char *swig_get_class() const {
  200. return swig_class.c_str();
  201. }
  202. /* acquire ownership of the wrapped Perl object (the sense of "disown" is from perl) */
  203. void swig_disown() const {
  204. if (!swig_disown_flag) {
  205. swig_disown_flag=true;
  206. swig_incref();
  207. }
  208. }
  209. /* increase the reference count of the wrapped Perl object */
  210. void swig_incref() const {
  211. if (swig_disown_flag) {
  212. SvREFCNT_inc(swig_self);
  213. }
  214. }
  215. /* methods to implement pseudo protected director members */
  216. virtual bool swig_get_inner(const char * /* swig_protected_method_name */) const {
  217. return true;
  218. }
  219. virtual void swig_set_inner(const char * /* swig_protected_method_name */, bool /* swig_val */) const {
  220. }
  221. /* ownership management */
  222. private:
  223. typedef std::map<void *, GCItem_var> swig_ownership_map;
  224. mutable swig_ownership_map swig_owner;
  225. public:
  226. template <typename Type>
  227. void swig_acquire_ownership_array(Type *vptr) const {
  228. if (vptr) {
  229. swig_owner[vptr] = new GCArray_T<Type>(vptr);
  230. }
  231. }
  232. template <typename Type>
  233. void swig_acquire_ownership(Type *vptr) const {
  234. if (vptr) {
  235. swig_owner[vptr] = new GCItem_T<Type>(vptr);
  236. }
  237. }
  238. void swig_acquire_ownership_obj(void *vptr, int own) const {
  239. if (vptr && own) {
  240. swig_owner[vptr] = new GCItem_Object(own);
  241. }
  242. }
  243. int swig_release_ownership(void *vptr) const {
  244. int own = 0;
  245. if (vptr) {
  246. swig_ownership_map::iterator iter = swig_owner.find(vptr);
  247. if (iter != swig_owner.end()) {
  248. own = iter->second->get_own();
  249. swig_owner.erase(iter);
  250. }
  251. }
  252. return own;
  253. }
  254. };
  255. }
  256. #endif