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 Ruby extensions. 9 * ----------------------------------------------------------------------------- */ 10 11/* 12 Use -DSWIG_DIRECTOR_NOUEH if you prefer to avoid the use of the 13 Undefined Exception Handler provided by swift 14*/ 15#ifndef SWIG_DIRECTOR_NOUEH 16#ifndef SWIG_DIRECTOR_UEH 17#define SWIG_DIRECTOR_UEH 18#endif 19#endif 20 21#ifdef __cplusplus 22 23#include <string> 24#include <iostream> 25#include <map> 26 27namespace Swig { 28 /* memory handler */ 29 struct GCItem 30 { 31 virtual ~GCItem() 32 { 33 } 34 35 virtual ruby_owntype get_own() const 36 { 37 return 0; 38 } 39 }; 40 41 struct GCItem_var 42 { 43 GCItem_var(GCItem *item = 0) : _item(item) 44 { 45 } 46 47 GCItem_var& operator=(GCItem *item) 48 { 49 GCItem *tmp = _item; 50 _item = item; 51 delete tmp; 52 return *this; 53 } 54 55 ~GCItem_var() 56 { 57 delete _item; 58 } 59 60 GCItem * operator->() const 61 { 62 return _item; 63 } 64 65 private: 66 GCItem *_item; 67 }; 68 69 70 template <typename Type> 71 struct GCItem_T : GCItem 72 { 73 GCItem_T(Type *ptr) : _ptr(ptr) 74 { 75 } 76 77 virtual ~GCItem_T() 78 { 79 delete _ptr; 80 } 81 82 private: 83 Type *_ptr; 84 }; 85 86 struct GCItem_Object : GCItem 87 { 88 GCItem_Object(ruby_owntype own) : _own(own) 89 { 90 } 91 92 virtual ~GCItem_Object() 93 { 94 } 95 96 ruby_owntype get_own() const 97 { 98 return _own; 99 } 100 101 private: 102 ruby_owntype _own; 103 }; 104 105 106 template <typename Type> 107 struct GCArray_T : GCItem 108 { 109 GCArray_T(Type *ptr) : _ptr(ptr) 110 { 111 } 112 113 virtual ~GCArray_T() 114 { 115 delete[] _ptr; 116 } 117 118 private: 119 Type *_ptr; 120 }; 121 122 123 /* body args */ 124 struct body_args { 125 VALUE recv; 126 ID id; 127 int argc; 128 VALUE *argv; 129 }; 130 131 /* Base class for director exceptions */ 132 class DirectorException { 133 protected: 134 VALUE swig_error; 135 std::string swig_msg; 136 protected: 137 DirectorException(VALUE error) 138 : swig_error(error) 139 { 140 } 141 142 DirectorException(VALUE error, const char* hdr, const char* msg ="") 143 : swig_error(error), swig_msg(hdr) { 144 if (strlen(msg)) { 145 swig_msg += " "; 146 swig_msg += msg; 147 } 148 if (swig_msg.size()) { 149 VALUE str = rb_str_new(swig_msg.data(), swig_msg.size()); 150 swig_error = rb_exc_new3(error, str); 151 } else { 152 swig_error = error; 153 } 154 } 155 public: 156 VALUE getType() const { 157 return CLASS_OF(swig_error); 158 } 159 VALUE getError() const { 160 return swig_error; 161 } 162 const std::string& getMessage() const 163 { 164 return swig_msg; 165 } 166 167 virtual ~DirectorException() {} 168 }; 169 170 /* unknown exception handler */ 171 172 class UnknownExceptionHandler 173 { 174#ifdef SWIG_DIRECTOR_UEH 175 static void handler() { 176 try { 177 throw; 178 } catch (DirectorException& e) { 179 std::cerr << "Swig Director exception caught:" << std::endl 180 << e.getMessage() << std::endl; 181 } catch (std::exception& e) { 182 std::cerr << "std::exception caught: "<< e.what() << std::endl; 183 } catch (...) { 184 std::cerr << "Unknown exception caught." << std::endl; 185 } 186 std::cerr << std::endl 187 << "Ruby interpreter traceback:" << std::endl; 188 std::cerr << std::endl; 189 std::cerr << "This exception was caught by the SWIG unexpected exception handler." << std::endl 190 << "Try using %feature(\"director:except\") to avoid reaching this point." << std::endl 191 << std::endl 192 << "Exception is being re-thrown, program will like abort/terminate." << std::endl; 193 throw; 194 } 195 196 public: 197 std::unexpected_handler old; 198 UnknownExceptionHandler(std::unexpected_handler nh = handler) 199 { 200 old = std::set_unexpected(nh); 201 } 202 203 ~UnknownExceptionHandler() 204 { 205 std::set_unexpected(old); 206 } 207#endif 208 }; 209 210 211 /* Type mismatch in the return value from a Ruby method call */ 212 class DirectorTypeMismatchException : public Swig::DirectorException { 213 public: 214 DirectorTypeMismatchException(VALUE error, const char *msg="") 215 : Swig::DirectorException(error, "Swig director type mismatch", msg) 216 { 217 } 218 219 DirectorTypeMismatchException(const char *msg="") 220 : Swig::DirectorException(rb_eTypeError, "Swig director type mismatch", msg) 221 { 222 } 223 224 static void raise(VALUE error, const char *msg) { 225 throw DirectorTypeMismatchException(error, msg); 226 } 227 228 static void raise(const char *msg) { 229 throw DirectorTypeMismatchException(msg); 230 } 231 }; 232 233 /* Any Ruby exception that occurs during a director method call */ 234 class DirectorMethodException : public Swig::DirectorException { 235 public: 236 DirectorMethodException(VALUE error) 237 : Swig::DirectorException(error) { 238 } 239 240 DirectorMethodException(const char* msg = "") 241 : Swig::DirectorException(rb_eRuntimeError, "Swig director method error.", msg) { 242 } 243 244 static void raise(VALUE error) 245 { 246 throw DirectorMethodException(error); 247 } 248 }; 249 250 /* Attempted to call a pure virtual method via a director method */ 251 class DirectorPureVirtualException : public Swig::DirectorException 252 { 253 public: 254 DirectorPureVirtualException(const char* msg = "") 255 : DirectorException(rb_eRuntimeError, "Swig director pure virtual method called", msg) 256 { 257 } 258 259 static void raise(const char *msg) 260 { 261 throw DirectorPureVirtualException(msg); 262 } 263 }; 264 265 /* Simple thread abstraction for pthreads on win32 */ 266#ifdef __THREAD__ 267# define __PTHREAD__ 268# if defined(_WIN32) || defined(__WIN32__) 269# define pthread_mutex_lock EnterCriticalSection 270# define pthread_mutex_unlock LeaveCriticalSection 271# define pthread_mutex_t CRITICAL_SECTION 272# define SWIG_MUTEX_INIT(var) var 273# else 274# include <pthread.h> 275# define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER 276# endif 277#endif 278 279#ifdef __PTHREAD__ 280 struct Guard 281 { 282 pthread_mutex_t *_mutex; 283 284 Guard(pthread_mutex_t &mutex) : _mutex(&mutex) 285 { 286 pthread_mutex_lock(_mutex); 287 } 288 289 ~Guard() 290 { 291 pthread_mutex_unlock(_mutex); 292 } 293 }; 294# define SWIG_GUARD(mutex) Guard _guard(mutex) 295#else 296# define SWIG_GUARD(mutex) 297#endif 298 299 /* director base class */ 300 class Director { 301 private: 302 /* pointer to the wrapped Ruby object */ 303 VALUE swig_self; 304 /* flag indicating whether the object is owned by Ruby or c++ */ 305 mutable bool swig_disown_flag; 306 307 public: 308 /* wrap a Ruby object, optionally taking ownership */ 309 Director(VALUE self) : swig_self(self), swig_disown_flag(false) { 310 } 311 312 /* discard our reference at destruction */ 313 virtual ~Director() { 314 } 315 316 /* return a pointer to the wrapped Ruby object */ 317 VALUE swig_get_self() const { 318 return swig_self; 319 } 320 321 /* acquire ownership of the wrapped Ruby object (the sense of "disown" 322 * is from Ruby) */ 323 void swig_disown() const { 324 if (!swig_disown_flag) { 325 swig_disown_flag = true; 326 } 327 } 328 329 /* ownership management */ 330 private: 331 typedef std::map<void*, GCItem_var> ownership_map; 332 mutable ownership_map owner; 333#ifdef __PTHREAD__ 334 static pthread_mutex_t swig_mutex_own; 335#endif 336 337 public: 338 template <typename Type> 339 void swig_acquire_ownership_array(Type *vptr) const 340 { 341 if (vptr) { 342 SWIG_GUARD(swig_mutex_own); 343 owner[vptr] = new GCArray_T<Type>(vptr); 344 } 345 } 346 347 template <typename Type> 348 void swig_acquire_ownership(Type *vptr) const 349 { 350 if (vptr) { 351 SWIG_GUARD(swig_mutex_own); 352 owner[vptr] = new GCItem_T<Type>(vptr); 353 } 354 } 355 356 void swig_acquire_ownership_obj(void *vptr, ruby_owntype own) const 357 { 358 if (vptr && own) { 359 SWIG_GUARD(swig_mutex_own); 360 owner[vptr] = new GCItem_Object(own); 361 } 362 } 363 364 ruby_owntype swig_release_ownership(void *vptr) const 365 { 366 ruby_owntype own = 0; 367 if (vptr) { 368 SWIG_GUARD(swig_mutex_own); 369 ownership_map::iterator iter = owner.find(vptr); 370 if (iter != owner.end()) { 371 own = iter->second->get_own(); 372 owner.erase(iter); 373 } 374 } 375 return own; 376 } 377 }; 378} 379 380#endif /* __cplusplus */ 381 382 383