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