From fbdc4d8e3c12b7dc0f8cd0ff3402134cdf42567e Mon Sep 17 00:00:00 2001 From: Marcelo Matus Date: Mon, 21 Nov 2005 21:01:35 +0000 Subject: [PATCH] fixes for directors + pointers git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7860 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/CHANGES.current | 48 +++++-- SWIG/Lib/python/director.swg | 17 ++- SWIG/Lib/python/director_h.swg | 239 +++++++++++++++++++++++++++----- SWIG/Lib/python/pyclasses.swg | 7 + SWIG/Lib/python/pycontainer.swg | 48 ++++++- SWIG/Lib/python/pyrun.swg | 50 +++++-- SWIG/Lib/python/pystrings.swg | 4 +- SWIG/Lib/ruby/director.swg | 231 ++++++++++++++++++++++++++++++ SWIG/Lib/ruby/rubyrun.swg | 31 ++++- SWIG/Lib/typemaps/ptrtypes.swg | 35 ++++- SWIG/Lib/typemaps/strings.swg | 42 ++++-- SWIG/Lib/typemaps/swigtype.swg | 24 +++- SWIG/Lib/typemaps/valtypes.swg | 10 +- SWIG/Lib/typemaps/void.swg | 5 +- SWIG/Source/Modules/python.cxx | 75 +++++++--- SWIG/Source/Modules/ruby.cxx | 79 +++++++---- 16 files changed, 808 insertions(+), 137 deletions(-) diff --git a/SWIG/CHANGES.current b/SWIG/CHANGES.current index 71428ab3c..a838bc3e0 100644 --- a/SWIG/CHANGES.current +++ b/SWIG/CHANGES.current @@ -1,6 +1,29 @@ Version 1.3.28 (unreleased). =========================== +11/21/2005: mmatus + [ruby + python] + Fixes for directors + pointers, ugly problem with not easy + solution. Before we identified this case as problematic: + + virtual const MyClass& my_method(); + + but it turns out that all the cases where a pointer, array or + reference is returned, are problematic, even for + primitive types (as int, double, char*, etc). + + To try to fix the issue, a new typemap was added, + 'directorfree', which is used to 'free' the resources + allocated during the 'directorout' phase. At the same + time, a primitive garbage collector engine was added to + deal with orphans addresses, when needed. + + The situation now is much better, but still you can have + memory exaustation if recursion is used. + + So, still you need to avoid returning pointers, arrays or + references when using director methods. + 11/14/2005: wsfulton More types added to windows.i, eg UINT8, WORD, BYTE etc. Including windows.i will also enable SWIG to parse the __declspec Microsoft @@ -69,26 +92,25 @@ Version 1.3.28 (unreleased). instance (not as in C++), only the last base class was properly deletted, or detected with directors. - Now the self.this element can be a list, which will - contain the C++ instance pointers for all the base - classes. + Now 'self.this' can be a list, which will contain the C++ + instance pointers for all the base classes. - - Now the 'this' pointer is responsible for deallocating - the C++ instance, and the __del__ method is not emitted - unless the user preppend/append some code to it. + Also, swig.this is responsible for deallocating the C++ + instance(s), and the __del__ method is not emitted unless + the user preppend/append some code to it. - - Swig now can detect memory leaks, ie, if you still - use the non-shadow module, and type something like + - Swig now can detect memory leaks, ie, if you still + use the non-shadow module, and type something like import _example f = _example.new_Foo() - and forgot to call _example.delete_Foo(f), then swig - will tell you that there is a memory leak. + and forgot to call _example.delete_Foo(f), then swig will + tell you that there is a memory leak. - Otherwise, if you always use the shadow module, probably - you will never ever see this warning unless there is - something wrong inside the swig wrapping code. + Otherwise, if you always use the shadow module, probably + you will never ever see this warning unless there is + something wrong inside the swig wrapping code. *** POTENTIAL INCOMPATIBILITY *** diff --git a/SWIG/Lib/python/director.swg b/SWIG/Lib/python/director.swg index 1d701083c..82bbe6f99 100644 --- a/SWIG/Lib/python/director.swg +++ b/SWIG/Lib/python/director.swg @@ -10,15 +10,30 @@ #ifdef __cplusplus namespace Swig { + + GCItem::~GCItem() + { + } + /* simple thread abstraction for pthreads on win32 */ Director::~Director() { swig_decref(); } + /* wrap a python object, optionally taking ownership */ + Director::Director(PyObject* self) : swig_self(self), swig_disown_flag(false) { +#ifdef __PTHREAD__ + MUTEX_INIT(swig_mutex_own); +#endif + swig_incref(); + } + + + bool Director::swig_up = false; #ifdef __PTHREAD__ - MUTEX_INIT(Director::swig_mutex_up); + pthread_mutex_t SWIG_MUTEX_INIT(Director::swig_mutex_up); pthread_t Director::swig_mutex_thread; bool Director::swig_mutex_active = false; #endif diff --git a/SWIG/Lib/python/director_h.swg b/SWIG/Lib/python/director_h.swg index a34cfd02a..7b17e2f78 100644 --- a/SWIG/Lib/python/director_h.swg +++ b/SWIG/Lib/python/director_h.swg @@ -14,6 +14,22 @@ #include #include #include +#include +#include + + +/* + Use -DSWIG_DIRECTOR_NOVTABLE if you don't want to generate a 'virtual + table', and avoid multiple GetAttr calls to retreive the python + methods. +*/ + +#ifndef SWIG_DIRECTOR_NOVTABLE +#ifndef SWIG_DIRECTOR_VTABLE +#define SWIG_DIRECTOR_VTABLE +#endif +#endif + /* @@ -50,6 +66,7 @@ # ifndef SWIG_DIRECTOR_RTDIR # define SWIG_DIRECTOR_RTDIR #include + namespace Swig { class Director; SWIGINTERN std::map& get_rtdir_map() { @@ -85,6 +102,117 @@ extern "C" { namespace Swig { + /* memory handler */ + struct GCItem + { + virtual ~GCItem() = 0; + + 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() + { + 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; + }; + + + /* unknown exception handler */ + class UnknownExceptionHandler + { + static void handler(); + public: + +#ifdef SWIG_DIRECTOR_UEH + std::unexpected_handler old; + UnknownExceptionHandler(std::unexpected_handler nh = handler) + { + old = std::set_unexpected(nh); + } + + ~UnknownExceptionHandler() + { + std::set_unexpected(old); + } +#endif + }; + /* base class for director exceptions */ class DirectorException { protected: @@ -120,25 +248,6 @@ namespace Swig { } }; - /* unknown exception handler */ - class UnknownExceptionHandler - { - static void handler(); - public: - -#ifdef SWIG_DIRECTOR_UEH - std::unexpected_handler old; - UnknownExceptionHandler(std::unexpected_handler nh = handler) - { - old = std::set_unexpected(nh); - } - - ~UnknownExceptionHandler() - { - std::set_unexpected(old); - } -#endif - }; /* type mismatch in the return value from a python method call */ class DirectorTypeMismatchException : public Swig::DirectorException { @@ -194,20 +303,41 @@ namespace Swig { }; - /* simple thread abstraction for pthreads on win32 */ +/* simple thread abstraction for pthreads on win32 */ #ifdef __THREAD__ -#define __PTHREAD__ -#if defined(_WIN32) || defined(__WIN32__) -#define pthread_mutex_lock EnterCriticalSection -#define pthread_mutex_unlock LeaveCriticalSection -#define pthread_mutex_t CRITICAL_SECTION -#define MUTEX_INIT(var) CRITICAL_SECTION var +# define __PTHREAD__ +# if defined(_WIN32) || defined(__WIN32__) +# define pthread_mutex_lock EnterCriticalSection +# define pthread_mutex_unlock LeaveCriticalSection +# define pthread_mutex_t CRITICAL_SECTION +# define SWIG_MUTEX_INIT(var) var +# endif #else -#include -#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER -#endif +# include +# define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER #endif +#ifdef __PTHREAD__ +# define SWIG_GUARD(mutex) Guard _guard(mutex) +#else +# define SWIG_GUARD(mutex) +#endif + + + struct Guard + { + pthread_mutex_t *_mutex; + + Guard(pthread_mutex_t &mutex) : _mutex(&mutex) + { + pthread_mutex_lock(_mutex); + } + + ~Guard() + { + pthread_mutex_unlock(_mutex); + } + }; /* director base class */ class Director { @@ -248,9 +378,7 @@ namespace Swig { public: /* wrap a python object, optionally taking ownership */ - Director(PyObject* self) : swig_self(self), swig_disown_flag(false) { - swig_incref(); - } + Director(PyObject* self); /* discard our reference at destruction */ virtual ~Director(); @@ -321,6 +449,53 @@ namespace Swig { virtual void swig_set_inner(const char* /* name */, bool /* val */) const { } + + /* ownership managing */ + private: + typedef std::map ownership_map; + mutable ownership_map owner; + mutable pthread_mutex_t swig_mutex_own; + + public: + template + void swig_acquire_ownership_array(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCArray_T(vptr); + } + } + + template + void swig_acquire_ownership(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCItem_T(vptr); + } + } + + void swig_acquire_ownership_obj(void *vptr, int own) const + { + if (vptr && own) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCItem_Object(own); + } + } + + int swig_release_ownership(void *vptr) const + { + int own = 0; + if (vptr) { + SWIG_GUARD(swig_mutex_own); + ownership_map::iterator iter = owner.find(vptr); + if (iter != owner.end()) { + own = iter->second->get_own(); + owner.erase(iter); + } + } + return own; + } }; } diff --git a/SWIG/Lib/python/pyclasses.swg b/SWIG/Lib/python/pyclasses.swg index cf6d9ddb7..03f828fbb 100644 --- a/SWIG/Lib/python/pyclasses.swg +++ b/SWIG/Lib/python/pyclasses.swg @@ -106,6 +106,13 @@ namespace swig { Hence, this class is purely internal and not visible at the wrapped side. */ +namespace swig { + %ignore PyObject_var; + struct PyObject_var {}; + %apply PyObject * {PyObject_var}; + %apply PyObject * const& {PyObject_var const&}; +} + %{ namespace swig { struct PyObject_var : PyObject_ptr { diff --git a/SWIG/Lib/python/pycontainer.swg b/SWIG/Lib/python/pycontainer.swg index 9008d7538..5a4c12e7e 100644 --- a/SWIG/Lib/python/pycontainer.swg +++ b/SWIG/Lib/python/pycontainer.swg @@ -44,7 +44,7 @@ namespace swig { template <> struct traits_check { - static bool check(PyObject *) { + static bool check(PyObject_ptr) { return true; } }; @@ -60,6 +60,41 @@ namespace swig { } +%fragment(SWIG_Traits_frag(swig::PyObject_var),"header",fragment="StdTraits") { +namespace swig { + template <> struct traits { + typedef value_category category; + static const char* type_name() { return "PyObject_var"; } + }; + + template <> struct traits_from { + typedef PyObject_var value_type; + static PyObject *from(const value_type& val) { + PyObject *obj = static_cast(val); + Py_XINCREF(obj); + return obj; + } + }; + + template <> + struct traits_check { + static bool check(PyObject_var) { + return true; + } + }; + + template <> struct traits_asval { + typedef PyObject_var value_type; + static int asval(PyObject *obj, value_type *val) { + if (val) *val = obj; + return SWIG_OK; + } + }; +} +} + + + %fragment("PySequence_Base","header") { @@ -79,6 +114,15 @@ namespace std { operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const { return PyObject_Compare(v, w) < 0; } }; + + template <> + struct less : public binary_function + { + bool + operator()(const swig::PyObject_var& v, const swig::PyObject_var& w) const + { return PyObject_Compare(v, w) < 0; } + }; + } namespace swig { @@ -706,7 +750,7 @@ namespace swig %fragment("PySequence_Cont"); - %newobject iterator(PyObject *PYTHON_SELF); + %newobject iterator(PyObject **PYTHON_SELF); %extend { swig::PySequence_OutputIterator* iterator(PyObject **PYTHON_SELF) { return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); diff --git a/SWIG/Lib/python/pyrun.swg b/SWIG/Lib/python/pyrun.swg index 3e5797eba..fcd56a85d 100644 --- a/SWIG/Lib/python/pyrun.swg +++ b/SWIG/Lib/python/pyrun.swg @@ -11,16 +11,19 @@ /* Common SWIG API */ /* for raw pointers */ -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) #define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) +#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) +#define swig_owntype int /* for raw packed data */ #define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) #define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) /* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) /* for C or C++ function pointers */ #define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) @@ -282,7 +285,7 @@ SWIGINTERN PyObject* PySwigObject_acquire(PyObject *v) { PySwigObject *sobj = (PySwigObject *)v; - sobj->own = 1; + sobj->own = SWIG_POINTER_OWN; Py_INCREF(Py_None); return Py_None; } @@ -642,7 +645,7 @@ SWIG_This() SWIGRUNTIMEINLINE PySwigObject * SWIG_Python_GetSwigThis(PyObject *pyobj) { - if (PySwigObject_Check(pyobj)) { + if (pyobj && PySwigObject_Check(pyobj)) { return (PySwigObject *) pyobj; } else { PyObject *obj = 0; @@ -663,17 +666,37 @@ SWIG_Python_GetSwigThis(PyObject *pyobj) obj = PyObject_GetAttr(pyobj,SWIG_This()); Py_XDECREF(obj); #endif - if (PyErr_Occurred()) { - obj = 0; + if (!obj || PyErr_Occurred()) { PyErr_Clear(); + return 0; + } + if (PySwigObject_Check(obj)) { + return (PySwigObject *)obj; + } else { + return 0; + } + } +} + +/* Acquire a pointer value */ +SWIGRUNTIME int +SWIG_Python_AcquirePtr(PyObject *obj, int own) { + if (own) { + PySwigObject *sobj = SWIG_Python_GetSwigThis(obj); + if (sobj) { + int oldown = sobj->own; + sobj->own = own; + return oldown; + } else { + return 0; } - return obj && PySwigObject_Check(obj) ? (PySwigObject *) obj : 0; } } /* Convert a pointer value */ + SWIGRUNTIME int -SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) { +SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { if (!obj) return SWIG_ERROR; if (obj == Py_None) { *ptr = 0; @@ -703,6 +726,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) } } if (sobj) { + if (own) *own = sobj->own; if (flags & SWIG_POINTER_DISOWN) { sobj->own = 0; } @@ -717,7 +741,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) SWIGRUNTIME int SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { if (!PyCFunction_Check(obj)) { - return SWIG_Python_ConvertPtr(obj, ptr, ty, 0); + return SWIG_ConvertPtr(obj, ptr, ty, 0); } else { const char *desc = 0; void *vptr = 0; @@ -814,7 +838,8 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { } return NULL; } else { - PyObject *robj = PySwigObject_New((void *) ptr, type, (flags & SWIG_POINTER_OWN)); + int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + PyObject *robj = PySwigObject_New((void *) ptr, type, own); PySwigClientData *clientdata = (PySwigClientData *)type->clientdata; if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); @@ -914,8 +939,7 @@ SWIG_Python_DestroyModule(void *vptr) ty->clientdata = 0; } } - Py_DECREF(SWIG_This()); - /* and, what else ... */ + Py_DECREF(SWIG_This()); } SWIGRUNTIME void diff --git a/SWIG/Lib/python/pystrings.swg b/SWIG/Lib/python/pystrings.swg index f28722abf..a90f333de 100644 --- a/SWIG/Lib/python/pystrings.swg +++ b/SWIG/Lib/python/pystrings.swg @@ -39,11 +39,11 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) *alloc = SWIG_NEWOBJ; } else { - *cptr = cstr; + *cptr = PyString_AsString(obj); *alloc = SWIG_OLDOBJ; } } else { - *cptr = cstr; + *cptr = PyString_AsString(obj); } } if (psize) *psize = len + 1; diff --git a/SWIG/Lib/ruby/director.swg b/SWIG/Lib/ruby/director.swg index 2ae2c6990..6d109bfbc 100644 --- a/SWIG/Lib/ruby/director.swg +++ b/SWIG/Lib/ruby/director.swg @@ -9,17 +9,144 @@ * Mark Rose (mrose@stm.lbl.gov). ************************************************************************/ +/* + Use -DSWIG_DIRECTOR_NOUEH if you prefer to avoid the use of the + Undefined Exception Handler provided by swift +*/ +#ifndef SWIG_DIRECTOR_NOUEH +#ifndef SWIG_DIRECTOR_UEH +#define SWIG_DIRECTOR_UEH +#endif +#endif + #ifdef __cplusplus #include +#include +#include namespace Swig { + /* memory handler */ + struct GCItem + { + virtual ~GCItem() = 0; + + virtual ruby_owntype 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; + }; + + + template + struct GCItem_T : GCItem + { + GCItem_T(Type *ptr) : _ptr(ptr) + { + } + + virtual ~GCItem_T() + { + delete _ptr; + } + + private: + Type *_ptr; + }; + + struct GCItem_Object : GCItem + { + GCItem_Object(ruby_owntype own) : _own(own) + { + } + + virtual ~GCItem_Object() + { + } + + ruby_owntype get_own() + { + return _own; + } + + private: + ruby_owntype _own; + }; + + + template + struct GCArray_T : GCItem + { + GCArray_T(Type *ptr) : _ptr(ptr) + { + } + + virtual ~GCArray_T() + { + delete[] _ptr; + } + + private: + Type *_ptr; + }; + + + /* body args */ + struct body_args { VALUE recv; ID id; int argc; VALUE *argv; }; + + /* unknown exception handler */ + class UnknownExceptionHandler + { + static void handler(); + public: + +#ifdef SWIG_DIRECTOR_UEH + std::unexpected_handler old; + UnknownExceptionHandler(std::unexpected_handler nh = handler) + { + old = std::set_unexpected(nh); + } + + ~UnknownExceptionHandler() + { + std::set_unexpected(old); + } +#endif + }; /* Base class for director exceptions */ class DirectorException { @@ -52,9 +179,15 @@ namespace Swig { VALUE getError() const { return swig_error; } + const std::string& getMessage() const + { + return swig_msg; + } + virtual ~DirectorException() {} }; + /* Type mismatch in the return value from a Ruby method call */ class DirectorTypeMismatchException : public Swig::DirectorException { public: @@ -123,6 +256,27 @@ namespace Swig { #endif #endif +#ifdef __PTHREAD__ +# define SWIG_GUARD(mutex) Guard _guard(mutex) +#else +# define SWIG_GUARD(mutex) +#endif + + struct Guard + { + pthread_mutex_t *_mutex; + + Guard(pthread_mutex_t &mutex) : _mutex(&mutex) + { + pthread_mutex_lock(_mutex); + } + + ~Guard() + { + pthread_mutex_unlock(_mutex); + } + }; + /* director base class */ class Director { private: @@ -212,6 +366,55 @@ namespace Swig { swig_disown_flag = true; } } + + /* ownership managing */ + private: + typedef std::map ownership_map; + mutable ownership_map owner; + mutable pthread_mutex_t swig_mutex_own; + + + public: + template + void swig_acquire_ownership_array(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCArray_T(vptr); + } + } + + template + void swig_acquire_ownership(Type *vptr) const + { + if (vptr) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCItem_T(vptr); + } + } + + void swig_acquire_ownership_obj(void *vptr, ruby_owntype own) const + { + if (vptr && own) { + SWIG_GUARD(swig_mutex_own); + owner[vptr] = new GCItem_Object(own); + } + } + + ruby_owntype swig_release_ownership(void *vptr) const + { + ruby_owntype own = 0; + if (vptr) { + SWIG_GUARD(swig_mutex_own); + ownership_map::iterator iter = owner.find(vptr); + if (iter != owner.end()) { + own = iter->second->get_own(); + owner.erase(iter); + } + } + return own; + } + }; bool Swig::Director::swig_up = false; @@ -222,6 +425,34 @@ namespace Swig { bool Swig::Director::swig_mutex_active = false; #endif + void UnknownExceptionHandler::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 + << "Ruby interpreter traceback:" << std::endl; + 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 like abort/terminate." << std::endl; + throw; + } + + + GCItem::~GCItem() + { + } + } #endif /* __cplusplus */ diff --git a/SWIG/Lib/ruby/rubyrun.swg b/SWIG/Lib/ruby/rubyrun.swg index f81d30286..8f4478b97 100644 --- a/SWIG/Lib/ruby/rubyrun.swg +++ b/SWIG/Lib/ruby/rubyrun.swg @@ -8,20 +8,23 @@ ************************************************************************/ /* for raw pointers */ -#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Ruby_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Ruby_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Ruby_ConvertPtrAndOwn(obj, pptr, type, flags, own) #define SWIG_NewPointerObj(ptr, type, flags) SWIG_Ruby_NewPointerObj(ptr, type, flags) +#define SWIG_AcquirePtr(ptr, own) SWIG_Ruby_AcquirePtr(ptr, own) +#define swig_owntype ruby_owntype /* for raw packed data */ #define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty, flags) #define SWIG_NewPackedObj(ptr, sz, type) SWIG_Ruby_NewPackedObj(ptr, sz, type) /* for class or struct pointers */ -#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Ruby_ConvertPtr(obj, pptr, type, flags) -#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Ruby_NewPointerObj(ptr, type, flags) +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) /* for C or C++ function pointers */ -#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Ruby_ConvertPtr(obj, pptr, type, 0) -#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Ruby_NewPointerObj(ptr, type, 0) +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0) /* for C++ member pointers, ie, member methods */ #define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty) @@ -162,9 +165,23 @@ SWIG_Ruby_MangleStr(VALUE obj) return StringValuePtr(stype); } +/* Acquire a pointer value */ +typedef void (*ruby_owntype)(void*); + +SWIGRUNTIME ruby_owntype +SWIG_Ruby_AcquirePtr(VALUE obj, ruby_owntype own) { + if (obj) { + ruby_owntype oldown = RDATA(obj)->dfree; + RDATA(obj)->dfree = own; + return oldown; + } else { + return 0; + } +} + /* Convert a pointer value */ SWIGRUNTIME int -SWIG_Ruby_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags) +SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags, ruby_owntype *own) { char *c; swig_cast_info *tc; @@ -186,6 +203,8 @@ SWIG_Ruby_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags) of the underlying C struct or C++ object. If so then we need to reset the destructor since the Ruby object no longer owns the underlying C++ object.*/ + if (own) *own = RDATA(obj)->dfree; + if (flags & SWIG_POINTER_DISOWN) { if (flags & SWIG_TRACK_OBJECTS) { /* We are tracking objects. Thus we change the destructor diff --git a/SWIG/Lib/typemaps/ptrtypes.swg b/SWIG/Lib/typemaps/ptrtypes.swg index 4c75064ff..ef739404e 100644 --- a/SWIG/Lib/typemaps/ptrtypes.swg +++ b/SWIG/Lib/typemaps/ptrtypes.swg @@ -82,7 +82,25 @@ if (ores == SWIG_NEWOBJ) %delete(optr); } - %typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) const Type& { + %typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) Type* { + Type *optr = 0; + int ores = asptr_meth($input, &optr); + if (!ores) { + %dirout_fail(SWIG_TypeError,"$type"); + } + $result = optr; + if (ores == SWIG_NEWOBJ) { + swig_acquire_ownership(optr); + } + } + %typemap(directorfree,noblock=1) Type* + { + if (director) { + director->swig_release_ownership(%as_voidptr($input)); + } + } + + %typemap(directorout,noblock=1,fragment=frag,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) Type& { Type *optr = 0; int ores = asptr_meth($input, &optr); if (!ores) { @@ -92,15 +110,18 @@ %dirout_nullref("$type"); } } + $result = optr; if (ores == SWIG_NEWOBJ) { - /* Possible thread/reentrant problem here! */ - static $*ltype temp = *optr; - $result = &temp; - %delete(optr); - } else { - $result = optr; + swig_acquire_ownership(optr); } } + %typemap(directorfree,noblock=1) Type& + { + if (director) { + director->swig_release_ownership(%as_voidptr($input)); + } + } + %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type diff --git a/SWIG/Lib/typemaps/strings.swg b/SWIG/Lib/typemaps/strings.swg index a203e1cf6..9d0d7fc0a 100644 --- a/SWIG/Lib/typemaps/strings.swg +++ b/SWIG/Lib/typemaps/strings.swg @@ -29,7 +29,7 @@ %typemap(in,noblock=1,fragment=#SWIG_AsCharPtr) Char * (Char *buf = 0, int alloc = 0), - const Char * (Char *buf = 0, int alloc = SWIG_OLDOBJ) { + const Char * (Char *buf = 0, int alloc = 0) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) { %argument_fail(SWIG_TypeError,"$type",$argnum); } @@ -157,21 +157,41 @@ /* directorout */ -%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr) - Char * (Char* buf = 0, int alloc = 0) { +%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) + Char * (Char* buf = 0, int alloc = SWIG_NEWOBJ) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) { %dirout_fail(SWIG_TypeError, "$type"); } + if (alloc == SWIG_NEWOBJ) { + swig_acquire_ownership_array(buf); + } $result = buf; } +%typemap(directorfree,noblock=1) Char * +{ + if (director) { + director->swig_release_ownership(%as_voidptr($input)); + } +} -%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr) - Char * const& (Char* buf = 0, int alloc = 0), - Char const* const& (Char* buf = 0, int alloc = 0) { + +%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) + Char * const& (Char* buf = 0, int alloc = SWIG_NEWOBJ), + Char const* const& (Char* buf = 0, int alloc = SWIG_NEWOBJ) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) { %dirout_fail(SWIG_TypeError, "$type"); } - $result = ($1_ltype) &buf; + static $*ltype tmp = buf; + $result = &tmp; + if (alloc == SWIG_NEWOBJ) { + swig_acquire_ownership_array(buf); + } +} +%typemap(directorfree,noblock=1) + Char * const&, Char const* const& { + if (director) { + director->swig_release_ownership(%as_voidptr(*$input)); + } } #endif /* SWIG_DIRECTOR_TYPEMAPS */ @@ -373,7 +393,7 @@ /* Here len doesn't include the '0' terminator */ %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) (Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = 0), - (const Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ) + (const Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = 0) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) { %argument_fail(SWIG_TypeError,"$type",$argnum); @@ -392,7 +412,7 @@ /* Here size includes the '0' terminator */ %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) (Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = 0), - (const Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ) + (const Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = 0) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) { %argument_fail(SWIG_TypeError,"$type",$argnum); @@ -413,7 +433,7 @@ /* Here len doesn't include the '0' terminator */ %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) (size_t LENGTH, Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0), - (size_t LENGHT, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ) + (size_t LENGHT, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) { %argument_fail(SWIG_TypeError,"$type",$argnum); @@ -431,7 +451,7 @@ /* Here size includes the '0' terminator */ %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) (size_t SIZE, Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0), - (size_t SIZE, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = SWIG_OLDOBJ) + (size_t SIZE, const Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) { %argument_fail(SWIG_TypeError, "$type",$argnum); diff --git a/SWIG/Lib/typemaps/swigtype.swg b/SWIG/Lib/typemaps/swigtype.swg index 4b47aeb83..4be5d08a7 100644 --- a/SWIG/Lib/typemaps/swigtype.swg +++ b/SWIG/Lib/typemaps/swigtype.swg @@ -272,19 +272,35 @@ } $result = *(%reinterpret_cast(argp, $<ype)); } -%typemap(directorout,noblock=1) SWIGTYPE *(void *argp), SWIGTYPE [](void *argp) { - if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) { +%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) + SWIGTYPE *(void *argp, swig_owntype own), SWIGTYPE [](void *argp, swig_owntype own) { + if (SWIG_ConvertPtrAndOwn($input, &argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own) != SWIG_OK) { %dirout_fail(SWIG_TypeError,"$type"); } $result = %reinterpret_cast(argp, $ltype); + swig_acquire_ownership_obj(%as_voidptr($result), own); } -%typemap(directorout,noblock=1) SWIGTYPE &(void *argp) { - if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) { +%typemap(directorfree,noblock=1) SWIGTYPE *, SWIGTYPE [] { + if (director) { + SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input))); + } +} + +%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) + SWIGTYPE &(void *argp, swig_owntype own) { + if (SWIG_ConvertPtrAndOwn($input, &argp, $descriptor, %convertptr_flags | SWIG_POINTER_DISOWN, &own) != SWIG_OK) { %dirout_fail(SWIG_TypeError,"$type"); } if (!argp) { %dirout_nullref("$type"); } $result = %reinterpret_cast(argp, $ltype); + swig_acquire_ownership_obj(%as_voidptr($result), own); } +%typemap(directorfree,noblock=1) SWIGTYPE & { + if (director) { + SWIG_AcquirePtr($result, director->swig_release_ownership(%as_voidptr($input))); + } +} + #endif /* SWIG_DIRECTOR_TYPEMAPS */ diff --git a/SWIG/Lib/typemaps/valtypes.swg b/SWIG/Lib/typemaps/valtypes.swg index b174f1dc1..778c69c5a 100644 --- a/SWIG/Lib/typemaps/valtypes.swg +++ b/SWIG/Lib/typemaps/valtypes.swg @@ -129,8 +129,14 @@ if (res != SWIG_OK) { %dirout_fail(res, "$type"); } - static $basetype temp = %static_cast(val, $basetype); - $result = &temp; + $basetype *temp = new $basetype(($basetype)val); + swig_acquire_ownership(temp); + $result = temp; + } + %typemap(directorfree,noblock=1) const Type & { + if (director) { + director->swig_release_ownership(%as_voidptr($input)); + } } %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type %enddef diff --git a/SWIG/Lib/typemaps/void.swg b/SWIG/Lib/typemaps/void.swg index c9f7af07b..c9e2e88ca 100644 --- a/SWIG/Lib/typemaps/void.swg +++ b/SWIG/Lib/typemaps/void.swg @@ -64,10 +64,11 @@ $result = %reinterpret_cast(argp, $ltype); } -%typemap(directorout,noblock=1) void * const& ($*ltype temp) { - if (SWIG_ConvertPtr($input, %as_voidptrptr(&temp), 0, $disown) != SWIG_OK) { +%typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) void * const& (void *argp) { + if (SWIG_ConvertPtr($input, &argp, 0, $disown) != SWIG_OK) { %dirout_fail(SWIG_TypeError,"$type"); } + static $*ltype temp = %reinterpret_cast(argp, $*ltype); $result = &temp; } diff --git a/SWIG/Source/Modules/python.cxx b/SWIG/Source/Modules/python.cxx index ee3d94555..7f40f157f 100644 --- a/SWIG/Source/Modules/python.cxx +++ b/SWIG/Source/Modules/python.cxx @@ -19,7 +19,6 @@ char cvsroot_python_cxx[] = "$Header$"; #define PYSHADOW_MEMBER 0x2 static String *const_code = 0; -static String *shadow_methods = 0; static String *module = 0; static String *package = 0; static String *mainmodule = 0; @@ -27,6 +26,7 @@ static String *interface = 0; static String *global_name = 0; static int shadow = 1; static int use_kw = 0; +static int director_method_index = 0; static File *f_runtime = 0; static File *f_runtime_h = 0; @@ -276,7 +276,6 @@ public: Swig_register_filebyname("director_h",f_directors_h); const_code = NewString(""); - shadow_methods = NewString(""); methods = NewString(""); Swig_banner(f_runtime); @@ -1153,7 +1152,7 @@ public: String *iname = Getattr(n,"sym:name"); SwigType *d = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); - Node *parent = Getattr(n,"parentNode"); + int director_method = 0; Parm *p; int i; @@ -1436,9 +1435,10 @@ public: if (!is_smart_pointer()) { if (/*directorbase &&*/ !constructor && !destructor && isVirtual && !Getattr(n,"feature:nodirector")) { + director_method = 1; Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Printf(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n"); - if (dirprot_mode() && !is_public(n)) { + if (dirprot_mode() && !is_public(n)) { Printf(f->code, "if (!director || !(director->swig_get_inner(\"%s\"))) {\n", name); Printf(f->code, "PyErr_SetString(PyExc_RuntimeError,\"accessing protected member %s\");\n", name); Printf(f->code, "SWIG_fail;\n"); @@ -1461,14 +1461,14 @@ public: */ /* Emit the function call */ - if (directorsEnabled()) { + if (director_method) { Printf(f->code, "try {\n"); Printf(f->code, " Swig::UnknownExceptionHandler dh;\n"); } emit_action(n,f); - if (directorsEnabled()) { + if (director_method) { Printf(f->code, "} catch (Swig::DirectorException&) {\n"); Printf(f->code, " SWIG_fail;\n"); Printf(f->code, "}\n"); @@ -1497,6 +1497,7 @@ public: /* New addition to unwrap director return values so that the original * python object is returned instead. */ +#if 1 int unwrap = 0; String *decl = Getattr(n, "decl"); int is_pointer = SwigType_ispointer_return(decl); @@ -1505,15 +1506,16 @@ public: String *type = Getattr(n, "type"); //Node *classNode = Swig_methodclass(n); //Node *module = Getattr(classNode, "module"); + Node *parent = Getattr(n,"parentNode"); Node *module = Getattr(parent, "module"); Node *target = Swig_directormap(module, type); if (target) unwrap = 1; } if (unwrap) { - Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0"); - Printf(f->code, "resultdirector = SWIG_DIRECTOR_CAST(result);\n"); - Printf(f->code, "if (resultdirector) {\n"); - Printf(f->code, " resultobj = resultdirector->swig_get_self();\n"); + Wrapper_add_local(f, "director", "Swig::Director *director = 0"); + Printf(f->code, "director = SWIG_DIRECTOR_CAST(result);\n"); + Printf(f->code, "if (director) {\n"); + Printf(f->code, " resultobj = director->swig_get_self();\n"); Printf(f->code, " Py_INCREF(resultobj);\n"); Printf(f->code, "} else {\n"); Printf(f->code,"%s\n", tm); @@ -1521,6 +1523,9 @@ public: } else { Printf(f->code,"%s\n", tm); } +#else + Printf(f->code,"%s\n", tm); +#endif } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d,0), name); @@ -1549,6 +1554,15 @@ public: Printf(f->code,"%s\n",tm); } + if (director_method) { + if ((tm = Swig_typemap_lookup_new("directorfree",n,"result",0))) { + Replaceall(tm,"$input","result"); + Replaceall(tm,"$result","resultobj"); + Printf(f->code,"%s\n",tm); + } + } + + Printf(f->code," return resultobj;\n"); /* Error handling code */ @@ -1815,6 +1829,8 @@ public: * ** Moved down due to gcc-2.96 internal error ** * --------------------------------------------------------------- */ + int classDirectorMethods(Node *n); + int classDirectorMethod(Node *n, Node *parent, String *super); /* ------------------------------------------------------------ @@ -1934,10 +1950,27 @@ public: Printf(f_directors_h," mutable std::map inner;\n"); } + + Printf(f_directors_h,"\n\n"); + Printf(f_directors_h,"/* VTable implementation */\n"); + Printf(f_directors_h,"public:\n"); + Printf(f_directors_h," PyObject *swig_get_method(size_t method_index, const char *method_name) const {\n"); + Printf(f_directors_h," PyObject *method = vtable[method_index];\n"); + Printf(f_directors_h," if (!method) {\n"); + Printf(f_directors_h," swig::PyObject_var name = PyString_FromString(method_name);\n"); + Printf(f_directors_h," vtable[method_index] = method = PyObject_GetAttr(swig_get_self(), name);\n"); + Printf(f_directors_h," Py_DECREF(swig_get_self());\n"); + Printf(f_directors_h," };\n"); + Printf(f_directors_h," return method;\n"); + Printf(f_directors_h," }\n\n"); + Printf(f_directors_h,"private:\n"); + Printf(f_directors_h," mutable swig::PyObject_var vtable[%d];\n", director_method_index); + Printf(f_directors_h, "};\n\n"); return Language::classDirectorEnd(n); } - + + /* ------------------------------------------------------------ * classDirectorDisown() * ------------------------------------------------------------ */ @@ -2614,7 +2647,7 @@ public: virtual String *defaultExternalRuntimeFilename() { return NewString("swigpyrun.h"); } - + }; /* --------------------------------------------------------------- @@ -2625,6 +2658,11 @@ public: * * ** Moved it here due to internal error on gcc-2.96 ** * --------------------------------------------------------------- */ +int PYTHON::classDirectorMethods(Node *n) { + director_method_index = 0; + return Language::classDirectorMethods(n); +} + int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { int is_void = 0; @@ -2856,9 +2894,8 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { /* add the method name as a PyString */ String *pyname = Getattr(n,"sym:name"); - String *tmp = NewStringf("static swig::PyObject_var swig_method_name = PyString_FromString(\"%s\")",pyname); - Wrapper_add_local(w, "swig_method_name", tmp); - Delete(tmp); + Wrapper_add_localv(w, "swig_method_index", "const size_t swig_method_index =", NewStringf("%d", director_method_index++), NIL); + Wrapper_add_localv(w, "swig_method_name", "const char * const swig_method_name =", NewStringf("\"%s\"",pyname), NIL); /* declare method return value * if the return value is a reference or const reference, a specialized typemap must @@ -2889,14 +2926,16 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { /* pass the method call on to the Python object */ - if (dirprot_mode() && !is_public(n)) + if (dirprot_mode() && !is_public(n)) { Printf(w->code, "swig_set_inner(\"%s\", true);\n", name); + } + Printf(w->code, "if (!swig_get_self()) {\n"); Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname); Printf(w->code, "}\n"); - Wrapper_add_local(w, "method", "swig::PyObject_var method = 0"); - Printf(w->code, "method = PyObject_GetAttr(swig_get_self(), swig_method_name);\n"); + Wrapper_add_local(w, "method", "PyObject* method = 0"); + Printf(w->code, "method = swig_get_method(swig_method_index, swig_method_name);\n"); Printf(w->code, "if (method == NULL) {\n"); Printf(w->code, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname); Printf(w->code, "}\n"); diff --git a/SWIG/Source/Modules/ruby.cxx b/SWIG/Source/Modules/ruby.cxx index 75e97843f..288f0b3c0 100644 --- a/SWIG/Source/Modules/ruby.cxx +++ b/SWIG/Source/Modules/ruby.cxx @@ -1082,7 +1082,7 @@ public: String *symname = Copy(Getattr(n,"sym:name")); SwigType *t = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); - Node *parent = Getattr(n,"parentNode"); + int director_method = 0; String *tm; int need_result = 0; @@ -1220,6 +1220,7 @@ public: if (!is_smart_pointer()) { if (/*directorbase &&*/ !constructor && !destructor && isVirtual && !Getattr(n,"feature:nodirector")) { + director_method = 1; Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Printf(f->code, "director = dynamic_cast(arg1);\n"); Printf(f->code, "if (director && (director->swig_get_self() == self)) director->swig_set_up();\n"); @@ -1244,7 +1245,20 @@ public: } } } + + /* Emit the function call */ + if (director_method) { + Printf(f->code, "try {\n"); + Printf(f->code, " Swig::UnknownExceptionHandler dh;\n"); + } + emit_action(n,f); + + if (director_method) { + Printf(f->code, "} catch (Swig::DirectorException&) {\n"); + Printf(f->code, " SWIG_fail;\n"); + Printf(f->code, "}\n"); + } } /* Return value if necessary */ @@ -1270,7 +1284,7 @@ public: Replaceall(tm, "$track","0"); } - +#if 1 // FIXME: this will not try to unwrap directors returned as non-director // base class pointers! @@ -1283,21 +1297,26 @@ public: int is_reference = SwigType_isreference_return(decl); if (is_pointer || is_reference) { String *type = Getattr(n, "type"); + Node *parent = Getattr(n,"parentNode"); Node *modname = Getattr(parent, "module"); Node *target = Swig_directormap(modname, type); if (target) unwrap = true; } if (unwrap) { - Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0"); - Printf(f->code, "resultdirector = dynamic_cast(result);\n"); - Printf(f->code, "if (resultdirector) {\n"); - Printf(f->code, " vresult = resultdirector->swig_get_self();\n"); + Wrapper_add_local(f, "director", "Swig::Director *director = 0"); + Printf(f->code, "director = dynamic_cast(result);\n"); + Printf(f->code, "if (director) {\n"); + Printf(f->code, " vresult = director->swig_get_self();\n"); Printf(f->code, "} else {\n"); Printf(f->code,"%s\n", tm); Printf(f->code, "}\n"); + director_method = 0; } else { Printf(f->code,"%s\n", tm); } +#else + Printf(f->code,"%s\n", tm); +#endif } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t,0)); @@ -1343,6 +1362,15 @@ public: Printv(f->code,tm, NIL); } + if (director_method) { + if ((tm = Swig_typemap_lookup_new("directorfree",n,"result",0))) { + Replaceall(tm,"$input","result"); + Replaceall(tm,"$result","vresult"); + Printf(f->code,"%s\n",tm); + } + } + + /* Wrap things up (in a manner of speaking) */ if (need_result) { if (current == CONSTRUCTOR_ALLOCATE) { @@ -2218,26 +2246,29 @@ public: if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) { // Declare a global to hold the depth count - Printf(f_directors, "static int %s = 0;\n", depthCountName); + if (!Getattr(n,"sym:nextSibling")) { + Printf(f_directors, "static int %s = 0;\n", depthCountName); - // Function body - Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName); - Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast(data)", NIL); - Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL); - Printf(body->code, "%s++;\n", depthCountName, NIL); - Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL); - Printf(body->code, "%s--;\n", depthCountName, NIL); - Printv(body->code, "return result;\n", NIL); - Printv(body->code, "}", NIL); + // Function body + Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName); + Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast(data)", NIL); + Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL); + Printf(body->code, "%s++;\n", depthCountName, NIL); + Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL); + Printf(body->code, "%s--;\n", depthCountName, NIL); + Printv(body->code, "return result;\n", NIL); + Printv(body->code, "}", NIL); + + // Exception handler + Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName); + Replaceall(tm, "$error", "error"); + Printf(rescue->code, "if (%s == 1) ", depthCountName); + Printv(rescue->code, Str(tm), "\n", NIL); + Printf(rescue->code, "%s--;\n", depthCountName); + Printv(rescue->code, "rb_exc_raise(error);\n", NIL); + Printv(rescue->code, "}", NIL); + } - // Exception handler - Printf(rescue->def, "VALUE %s(VALUE args, VALUE error) {\n", rescueName); - Replaceall(tm, "$error", "error"); - Printf(rescue->code, "if (%s == 1) ", depthCountName); - Printv(rescue->code, Str(tm), "\n", NIL); - Printf(rescue->code, "%s--;\n", depthCountName); - Printv(rescue->code, "rb_exc_raise(error);\n", NIL); - Printv(rescue->code, "}", NIL); // Main code Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);