fixes for directors + pointers

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7860 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2005-11-21 21:01:35 +00:00
commit fbdc4d8e3c
16 changed files with 808 additions and 137 deletions

View file

@ -1,6 +1,29 @@
Version 1.3.28 (unreleased). 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 11/14/2005: wsfulton
More types added to windows.i, eg UINT8, WORD, BYTE etc. More types added to windows.i, eg UINT8, WORD, BYTE etc.
Including windows.i will also enable SWIG to parse the __declspec Microsoft 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 instance (not as in C++), only the last base class was
properly deletted, or detected with directors. properly deletted, or detected with directors.
Now the self.this element can be a list, which will Now 'self.this' can be a list, which will contain the C++
contain the C++ instance pointers for all the base instance pointers for all the base classes.
classes.
- Now the 'this' pointer is responsible for deallocating Also, swig.this is responsible for deallocating the C++
the C++ instance, and the __del__ method is not emitted instance(s), and the __del__ method is not emitted unless
unless the user preppend/append some code to it. the user preppend/append some code to it.
- Swig now can detect memory leaks, ie, if you still - Swig now can detect memory leaks, ie, if you still
use the non-shadow module, and type something like use the non-shadow module, and type something like
import _example import _example
f = _example.new_Foo() f = _example.new_Foo()
and forgot to call _example.delete_Foo(f), then swig and forgot to call _example.delete_Foo(f), then swig will
will tell you that there is a memory leak. tell you that there is a memory leak.
Otherwise, if you always use the shadow module, probably Otherwise, if you always use the shadow module, probably
you will never ever see this warning unless there is you will never ever see this warning unless there is
something wrong inside the swig wrapping code. something wrong inside the swig wrapping code.
*** POTENTIAL INCOMPATIBILITY *** *** POTENTIAL INCOMPATIBILITY ***

View file

@ -10,15 +10,30 @@
#ifdef __cplusplus #ifdef __cplusplus
namespace Swig { namespace Swig {
GCItem::~GCItem()
{
}
/* simple thread abstraction for pthreads on win32 */ /* simple thread abstraction for pthreads on win32 */
Director::~Director() { Director::~Director() {
swig_decref(); 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; bool Director::swig_up = false;
#ifdef __PTHREAD__ #ifdef __PTHREAD__
MUTEX_INIT(Director::swig_mutex_up); pthread_mutex_t SWIG_MUTEX_INIT(Director::swig_mutex_up);
pthread_t Director::swig_mutex_thread; pthread_t Director::swig_mutex_thread;
bool Director::swig_mutex_active = false; bool Director::swig_mutex_active = false;
#endif #endif

View file

@ -14,6 +14,22 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <exception> #include <exception>
#include <vector>
#include <map>
/*
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 # ifndef SWIG_DIRECTOR_RTDIR
# define SWIG_DIRECTOR_RTDIR # define SWIG_DIRECTOR_RTDIR
#include <map> #include <map>
namespace Swig { namespace Swig {
class Director; class Director;
SWIGINTERN std::map<void*,Director*>& get_rtdir_map() { SWIGINTERN std::map<void*,Director*>& get_rtdir_map() {
@ -85,6 +102,117 @@ extern "C" {
namespace Swig { 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 <typename Type>
struct GCItem_T : GCItem
{
GCItem_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCItem_T()
{
delete _ptr;
}
private:
Type *_ptr;
};
template <typename Type>
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 */ /* base class for director exceptions */
class DirectorException { class DirectorException {
protected: 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 */ /* type mismatch in the return value from a python method call */
class DirectorTypeMismatchException : public Swig::DirectorException { 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__ #ifdef __THREAD__
#define __PTHREAD__ # define __PTHREAD__
#if defined(_WIN32) || defined(__WIN32__) # if defined(_WIN32) || defined(__WIN32__)
#define pthread_mutex_lock EnterCriticalSection # define pthread_mutex_lock EnterCriticalSection
#define pthread_mutex_unlock LeaveCriticalSection # define pthread_mutex_unlock LeaveCriticalSection
#define pthread_mutex_t CRITICAL_SECTION # define pthread_mutex_t CRITICAL_SECTION
#define MUTEX_INIT(var) CRITICAL_SECTION var # define SWIG_MUTEX_INIT(var) var
# endif
#else #else
#include <pthread.h> # include <pthread.h>
#define MUTEX_INIT(var) pthread_mutex_t var = PTHREAD_MUTEX_INITIALIZER # define SWIG_MUTEX_INIT(var) var = PTHREAD_MUTEX_INITIALIZER
#endif
#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 */ /* director base class */
class Director { class Director {
@ -248,9 +378,7 @@ namespace Swig {
public: public:
/* wrap a python object, optionally taking ownership */ /* wrap a python object, optionally taking ownership */
Director(PyObject* self) : swig_self(self), swig_disown_flag(false) { Director(PyObject* self);
swig_incref();
}
/* discard our reference at destruction */ /* discard our reference at destruction */
virtual ~Director(); virtual ~Director();
@ -321,6 +449,53 @@ namespace Swig {
virtual void swig_set_inner(const char* /* name */, bool /* val */) const { virtual void swig_set_inner(const char* /* name */, bool /* val */) const {
} }
/* ownership managing */
private:
typedef std::map<void*, GCItem_var> ownership_map;
mutable ownership_map owner;
mutable pthread_mutex_t swig_mutex_own;
public:
template <typename Type>
void swig_acquire_ownership_array(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCArray_T<Type>(vptr);
}
}
template <typename Type>
void swig_acquire_ownership(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_T<Type>(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;
}
}; };
} }

View file

@ -106,6 +106,13 @@ namespace swig {
Hence, this class is purely internal and not visible at the wrapped side. 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 { namespace swig {
struct PyObject_var : PyObject_ptr { struct PyObject_var : PyObject_ptr {

View file

@ -44,7 +44,7 @@ namespace swig {
template <> template <>
struct traits_check<PyObject_ptr, value_category> { struct traits_check<PyObject_ptr, value_category> {
static bool check(PyObject *) { static bool check(PyObject_ptr) {
return true; return true;
} }
}; };
@ -60,6 +60,41 @@ namespace swig {
} }
%fragment(SWIG_Traits_frag(swig::PyObject_var),"header",fragment="StdTraits") {
namespace swig {
template <> struct traits<PyObject_var > {
typedef value_category category;
static const char* type_name() { return "PyObject_var"; }
};
template <> struct traits_from<PyObject_var> {
typedef PyObject_var value_type;
static PyObject *from(const value_type& val) {
PyObject *obj = static_cast<PyObject *>(val);
Py_XINCREF(obj);
return obj;
}
};
template <>
struct traits_check<PyObject_var, value_category> {
static bool check(PyObject_var) {
return true;
}
};
template <> struct traits_asval<PyObject_var > {
typedef PyObject_var value_type;
static int asval(PyObject *obj, value_type *val) {
if (val) *val = obj;
return SWIG_OK;
}
};
}
}
%fragment("PySequence_Base","header") %fragment("PySequence_Base","header")
{ {
@ -79,6 +114,15 @@ namespace std {
operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const
{ return PyObject_Compare(v, w) < 0; } { return PyObject_Compare(v, w) < 0; }
}; };
template <>
struct less <swig::PyObject_var>: public binary_function<swig::PyObject_var, swig::PyObject_var, bool>
{
bool
operator()(const swig::PyObject_var& v, const swig::PyObject_var& w) const
{ return PyObject_Compare(v, w) < 0; }
};
} }
namespace swig { namespace swig {
@ -706,7 +750,7 @@ namespace swig
%fragment("PySequence_Cont"); %fragment("PySequence_Cont");
%newobject iterator(PyObject *PYTHON_SELF); %newobject iterator(PyObject **PYTHON_SELF);
%extend { %extend {
swig::PySequence_OutputIterator* iterator(PyObject **PYTHON_SELF) { swig::PySequence_OutputIterator* iterator(PyObject **PYTHON_SELF) {
return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF); return swig::make_output_iterator(self->begin(), self->begin(), self->end(), *PYTHON_SELF);

View file

@ -11,16 +11,19 @@
/* Common SWIG API */ /* Common SWIG API */
/* for raw pointers */ /* 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_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 */ /* for raw packed data */
#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) #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) #define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type)
/* for class or struct pointers */ /* for class or struct pointers */
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) #define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Python_NewPointerObj(ptr, type, flags) #define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
/* for C or C++ function pointers */ /* for C or C++ function pointers */
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) #define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type)
@ -282,7 +285,7 @@ SWIGINTERN PyObject*
PySwigObject_acquire(PyObject *v) PySwigObject_acquire(PyObject *v)
{ {
PySwigObject *sobj = (PySwigObject *)v; PySwigObject *sobj = (PySwigObject *)v;
sobj->own = 1; sobj->own = SWIG_POINTER_OWN;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
@ -642,7 +645,7 @@ SWIG_This()
SWIGRUNTIMEINLINE PySwigObject * SWIGRUNTIMEINLINE PySwigObject *
SWIG_Python_GetSwigThis(PyObject *pyobj) SWIG_Python_GetSwigThis(PyObject *pyobj)
{ {
if (PySwigObject_Check(pyobj)) { if (pyobj && PySwigObject_Check(pyobj)) {
return (PySwigObject *) pyobj; return (PySwigObject *) pyobj;
} else { } else {
PyObject *obj = 0; PyObject *obj = 0;
@ -663,17 +666,37 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
obj = PyObject_GetAttr(pyobj,SWIG_This()); obj = PyObject_GetAttr(pyobj,SWIG_This());
Py_XDECREF(obj); Py_XDECREF(obj);
#endif #endif
if (PyErr_Occurred()) { if (!obj || PyErr_Occurred()) {
obj = 0;
PyErr_Clear(); 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 */ /* Convert a pointer value */
SWIGRUNTIME int 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) return SWIG_ERROR;
if (obj == Py_None) { if (obj == Py_None) {
*ptr = 0; *ptr = 0;
@ -703,6 +726,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)
} }
} }
if (sobj) { if (sobj) {
if (own) *own = sobj->own;
if (flags & SWIG_POINTER_DISOWN) { if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0; sobj->own = 0;
} }
@ -717,7 +741,7 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)
SWIGRUNTIME int SWIGRUNTIME int
SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
if (!PyCFunction_Check(obj)) { if (!PyCFunction_Check(obj)) {
return SWIG_Python_ConvertPtr(obj, ptr, ty, 0); return SWIG_ConvertPtr(obj, ptr, ty, 0);
} else { } else {
const char *desc = 0; const char *desc = 0;
void *vptr = 0; void *vptr = 0;
@ -814,7 +838,8 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
} }
return NULL; return NULL;
} else { } 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; PySwigClientData *clientdata = (PySwigClientData *)type->clientdata;
if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
@ -914,8 +939,7 @@ SWIG_Python_DestroyModule(void *vptr)
ty->clientdata = 0; ty->clientdata = 0;
} }
} }
Py_DECREF(SWIG_This()); Py_DECREF(SWIG_This());
/* and, what else ... */
} }
SWIGRUNTIME void SWIGRUNTIME void

View file

@ -39,11 +39,11 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
*alloc = SWIG_NEWOBJ; *alloc = SWIG_NEWOBJ;
} }
else { else {
*cptr = cstr; *cptr = PyString_AsString(obj);
*alloc = SWIG_OLDOBJ; *alloc = SWIG_OLDOBJ;
} }
} else { } else {
*cptr = cstr; *cptr = PyString_AsString(obj);
} }
} }
if (psize) *psize = len + 1; if (psize) *psize = len + 1;

View file

@ -9,17 +9,144 @@
* Mark Rose (mrose@stm.lbl.gov). * 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 #ifdef __cplusplus
#include <string> #include <string>
#include <iostream>
#include <map>
namespace Swig { 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 <typename Type>
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 <typename Type>
struct GCArray_T : GCItem
{
GCArray_T(Type *ptr) : _ptr(ptr)
{
}
virtual ~GCArray_T()
{
delete[] _ptr;
}
private:
Type *_ptr;
};
/* body args */
struct body_args { struct body_args {
VALUE recv; VALUE recv;
ID id; ID id;
int argc; int argc;
VALUE *argv; 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 */ /* Base class for director exceptions */
class DirectorException { class DirectorException {
@ -52,9 +179,15 @@ namespace Swig {
VALUE getError() const { VALUE getError() const {
return swig_error; return swig_error;
} }
const std::string& getMessage() const
{
return swig_msg;
}
virtual ~DirectorException() {} virtual ~DirectorException() {}
}; };
/* Type mismatch in the return value from a Ruby method call */ /* Type mismatch in the return value from a Ruby method call */
class DirectorTypeMismatchException : public Swig::DirectorException { class DirectorTypeMismatchException : public Swig::DirectorException {
public: public:
@ -123,6 +256,27 @@ namespace Swig {
#endif #endif
#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 */ /* director base class */
class Director { class Director {
private: private:
@ -212,6 +366,55 @@ namespace Swig {
swig_disown_flag = true; swig_disown_flag = true;
} }
} }
/* ownership managing */
private:
typedef std::map<void*, GCItem_var> ownership_map;
mutable ownership_map owner;
mutable pthread_mutex_t swig_mutex_own;
public:
template <typename Type>
void swig_acquire_ownership_array(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCArray_T<Type>(vptr);
}
}
template <typename Type>
void swig_acquire_ownership(Type *vptr) const
{
if (vptr) {
SWIG_GUARD(swig_mutex_own);
owner[vptr] = new GCItem_T<Type>(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; bool Swig::Director::swig_up = false;
@ -222,6 +425,34 @@ namespace Swig {
bool Swig::Director::swig_mutex_active = false; bool Swig::Director::swig_mutex_active = false;
#endif #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 */ #endif /* __cplusplus */

View file

@ -8,20 +8,23 @@
************************************************************************/ ************************************************************************/
/* for raw pointers */ /* 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_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 */ /* for raw packed data */
#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty, flags) #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) #define SWIG_NewPackedObj(ptr, sz, type) SWIG_Ruby_NewPackedObj(ptr, sz, type)
/* for class or struct pointers */ /* for class or struct pointers */
#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_Ruby_ConvertPtr(obj, pptr, type, flags) #define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags)
#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_Ruby_NewPointerObj(ptr, type, flags) #define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags)
/* for C or C++ function pointers */ /* for C or C++ function pointers */
#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Ruby_ConvertPtr(obj, pptr, type, 0) #define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_ConvertPtr(obj, pptr, type, 0)
#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Ruby_NewPointerObj(ptr, type, 0) #define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NewPointerObj(ptr, type, 0)
/* for C++ member pointers, ie, member methods */ /* for C++ member pointers, ie, member methods */
#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Ruby_ConvertPacked(obj, ptr, sz, ty) #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); 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 */ /* Convert a pointer value */
SWIGRUNTIME int 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; char *c;
swig_cast_info *tc; 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 of the underlying C struct or C++ object. If so then we
need to reset the destructor since the Ruby object no need to reset the destructor since the Ruby object no
longer owns the underlying C++ object.*/ longer owns the underlying C++ object.*/
if (own) *own = RDATA(obj)->dfree;
if (flags & SWIG_POINTER_DISOWN) { if (flags & SWIG_POINTER_DISOWN) {
if (flags & SWIG_TRACK_OBJECTS) { if (flags & SWIG_TRACK_OBJECTS) {
/* We are tracking objects. Thus we change the destructor /* We are tracking objects. Thus we change the destructor

View file

@ -82,7 +82,25 @@
if (ores == SWIG_NEWOBJ) %delete(optr); 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; Type *optr = 0;
int ores = asptr_meth($input, &optr); int ores = asptr_meth($input, &optr);
if (!ores) { if (!ores) {
@ -92,15 +110,18 @@
%dirout_nullref("$type"); %dirout_nullref("$type");
} }
} }
$result = optr;
if (ores == SWIG_NEWOBJ) { if (ores == SWIG_NEWOBJ) {
/* Possible thread/reentrant problem here! */ swig_acquire_ownership(optr);
static $*ltype temp = *optr;
$result = &temp;
%delete(optr);
} else {
$result = optr;
} }
} }
%typemap(directorfree,noblock=1) Type&
{
if (director) {
director->swig_release_ownership(%as_voidptr($input));
}
}
%typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type

View file

@ -29,7 +29,7 @@
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtr) %typemap(in,noblock=1,fragment=#SWIG_AsCharPtr)
Char * (Char *buf = 0, int alloc = 0), 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) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum); %argument_fail(SWIG_TypeError,"$type",$argnum);
} }
@ -157,21 +157,41 @@
/* directorout */ /* directorout */
%typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr) %typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
Char * (Char* buf = 0, int alloc = 0) { Char * (Char* buf = 0, int alloc = SWIG_NEWOBJ) {
if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%dirout_fail(SWIG_TypeError, "$type"); %dirout_fail(SWIG_TypeError, "$type");
} }
if (alloc == SWIG_NEWOBJ) {
swig_acquire_ownership_array(buf);
}
$result = 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), %typemap(directorout,noblock=1,fragment=#SWIG_AsCharPtr,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
Char const* const& (Char* buf = 0, int alloc = 0) { 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) { if (SWIG_AsCharPtr($input, &buf, &alloc) != SWIG_OK) {
%dirout_fail(SWIG_TypeError, "$type"); %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 */ #endif /* SWIG_DIRECTOR_TYPEMAPS */
@ -373,7 +393,7 @@
/* Here len doesn't include the '0' terminator */ /* Here len doesn't include the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(Char *STRING, size_t LENGTH) (Char *buf = 0, size_t size = 0, int alloc = 0), (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) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum); %argument_fail(SWIG_TypeError,"$type",$argnum);
@ -392,7 +412,7 @@
/* Here size includes the '0' terminator */ /* Here size includes the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(Char *STRING, size_t SIZE) (Char *buf = 0, size_t size = 0, int alloc = 0), (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) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum); %argument_fail(SWIG_TypeError,"$type",$argnum);
@ -413,7 +433,7 @@
/* Here len doesn't include the '0' terminator */ /* Here len doesn't include the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) %typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(size_t LENGTH, Char *STRING) (Char *buf = 0, size_t size = 0, int alloc = 0), (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) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError,"$type",$argnum); %argument_fail(SWIG_TypeError,"$type",$argnum);
@ -431,7 +451,7 @@
/* Here size includes the '0' terminator */ /* Here size includes the '0' terminator */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize) %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, 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) { if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK) {
%argument_fail(SWIG_TypeError, "$type",$argnum); %argument_fail(SWIG_TypeError, "$type",$argnum);

View file

@ -272,19 +272,35 @@
} }
$result = *(%reinterpret_cast(argp, $&ltype)); $result = *(%reinterpret_cast(argp, $&ltype));
} }
%typemap(directorout,noblock=1) SWIGTYPE *(void *argp), SWIGTYPE [](void *argp) { %typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE)
if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) { 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"); %dirout_fail(SWIG_TypeError,"$type");
} }
$result = %reinterpret_cast(argp, $ltype); $result = %reinterpret_cast(argp, $ltype);
swig_acquire_ownership_obj(%as_voidptr($result), own);
} }
%typemap(directorout,noblock=1) SWIGTYPE &(void *argp) { %typemap(directorfree,noblock=1) SWIGTYPE *, SWIGTYPE [] {
if (SWIG_ConvertPtr($input, &argp, $descriptor, %convertptr_flags) != SWIG_OK) { 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"); %dirout_fail(SWIG_TypeError,"$type");
} }
if (!argp) { %dirout_nullref("$type"); } if (!argp) { %dirout_nullref("$type"); }
$result = %reinterpret_cast(argp, $ltype); $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 */ #endif /* SWIG_DIRECTOR_TYPEMAPS */

View file

@ -129,8 +129,14 @@
if (res != SWIG_OK) { if (res != SWIG_OK) {
%dirout_fail(res, "$type"); %dirout_fail(res, "$type");
} }
static $basetype temp = %static_cast(val, $basetype); $basetype *temp = new $basetype(($basetype)val);
$result = &temp; 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 %typemap(directorout,fragment=frag) Type &DIRECTOROUT = Type
%enddef %enddef

View file

@ -64,10 +64,11 @@
$result = %reinterpret_cast(argp, $ltype); $result = %reinterpret_cast(argp, $ltype);
} }
%typemap(directorout,noblock=1) void * const& ($*ltype temp) { %typemap(directorout,noblock=1,warning=SWIG_WARN_TYPEMAP_THREAD_UNSAFE) void * const& (void *argp) {
if (SWIG_ConvertPtr($input, %as_voidptrptr(&temp), 0, $disown) != SWIG_OK) { if (SWIG_ConvertPtr($input, &argp, 0, $disown) != SWIG_OK) {
%dirout_fail(SWIG_TypeError,"$type"); %dirout_fail(SWIG_TypeError,"$type");
} }
static $*ltype temp = %reinterpret_cast(argp, $*ltype);
$result = &temp; $result = &temp;
} }

View file

@ -19,7 +19,6 @@ char cvsroot_python_cxx[] = "$Header$";
#define PYSHADOW_MEMBER 0x2 #define PYSHADOW_MEMBER 0x2
static String *const_code = 0; static String *const_code = 0;
static String *shadow_methods = 0;
static String *module = 0; static String *module = 0;
static String *package = 0; static String *package = 0;
static String *mainmodule = 0; static String *mainmodule = 0;
@ -27,6 +26,7 @@ static String *interface = 0;
static String *global_name = 0; static String *global_name = 0;
static int shadow = 1; static int shadow = 1;
static int use_kw = 0; static int use_kw = 0;
static int director_method_index = 0;
static File *f_runtime = 0; static File *f_runtime = 0;
static File *f_runtime_h = 0; static File *f_runtime_h = 0;
@ -276,7 +276,6 @@ public:
Swig_register_filebyname("director_h",f_directors_h); Swig_register_filebyname("director_h",f_directors_h);
const_code = NewString(""); const_code = NewString("");
shadow_methods = NewString("");
methods = NewString(""); methods = NewString("");
Swig_banner(f_runtime); Swig_banner(f_runtime);
@ -1153,7 +1152,7 @@ public:
String *iname = Getattr(n,"sym:name"); String *iname = Getattr(n,"sym:name");
SwigType *d = Getattr(n,"type"); SwigType *d = Getattr(n,"type");
ParmList *l = Getattr(n,"parms"); ParmList *l = Getattr(n,"parms");
Node *parent = Getattr(n,"parentNode"); int director_method = 0;
Parm *p; Parm *p;
int i; int i;
@ -1436,9 +1435,10 @@ public:
if (!is_smart_pointer()) { if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) { && isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = SWIG_DIRECTOR_CAST(arg1);\n"); 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, "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, "PyErr_SetString(PyExc_RuntimeError,\"accessing protected member %s\");\n", name);
Printf(f->code, "SWIG_fail;\n"); Printf(f->code, "SWIG_fail;\n");
@ -1461,14 +1461,14 @@ public:
*/ */
/* Emit the function call */ /* Emit the function call */
if (directorsEnabled()) { if (director_method) {
Printf(f->code, "try {\n"); Printf(f->code, "try {\n");
Printf(f->code, " Swig::UnknownExceptionHandler dh;\n"); Printf(f->code, " Swig::UnknownExceptionHandler dh;\n");
} }
emit_action(n,f); emit_action(n,f);
if (directorsEnabled()) { if (director_method) {
Printf(f->code, "} catch (Swig::DirectorException&) {\n"); Printf(f->code, "} catch (Swig::DirectorException&) {\n");
Printf(f->code, " SWIG_fail;\n"); Printf(f->code, " SWIG_fail;\n");
Printf(f->code, "}\n"); Printf(f->code, "}\n");
@ -1497,6 +1497,7 @@ public:
/* New addition to unwrap director return values so that the original /* New addition to unwrap director return values so that the original
* python object is returned instead. * python object is returned instead.
*/ */
#if 1
int unwrap = 0; int unwrap = 0;
String *decl = Getattr(n, "decl"); String *decl = Getattr(n, "decl");
int is_pointer = SwigType_ispointer_return(decl); int is_pointer = SwigType_ispointer_return(decl);
@ -1505,15 +1506,16 @@ public:
String *type = Getattr(n, "type"); String *type = Getattr(n, "type");
//Node *classNode = Swig_methodclass(n); //Node *classNode = Swig_methodclass(n);
//Node *module = Getattr(classNode, "module"); //Node *module = Getattr(classNode, "module");
Node *parent = Getattr(n,"parentNode");
Node *module = Getattr(parent, "module"); Node *module = Getattr(parent, "module");
Node *target = Swig_directormap(module, type); Node *target = Swig_directormap(module, type);
if (target) unwrap = 1; if (target) unwrap = 1;
} }
if (unwrap) { if (unwrap) {
Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0"); Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "resultdirector = SWIG_DIRECTOR_CAST(result);\n"); Printf(f->code, "director = SWIG_DIRECTOR_CAST(result);\n");
Printf(f->code, "if (resultdirector) {\n"); Printf(f->code, "if (director) {\n");
Printf(f->code, " resultobj = resultdirector->swig_get_self();\n"); Printf(f->code, " resultobj = director->swig_get_self();\n");
Printf(f->code, " Py_INCREF(resultobj);\n"); Printf(f->code, " Py_INCREF(resultobj);\n");
Printf(f->code, "} else {\n"); Printf(f->code, "} else {\n");
Printf(f->code,"%s\n", tm); Printf(f->code,"%s\n", tm);
@ -1521,6 +1523,9 @@ public:
} else { } else {
Printf(f->code,"%s\n", tm); Printf(f->code,"%s\n", tm);
} }
#else
Printf(f->code,"%s\n", tm);
#endif
} else { } else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, 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); "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); 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"); Printf(f->code," return resultobj;\n");
/* Error handling code */ /* Error handling code */
@ -1815,6 +1829,8 @@ public:
* ** Moved down due to gcc-2.96 internal error ** * ** Moved down due to gcc-2.96 internal error **
* --------------------------------------------------------------- */ * --------------------------------------------------------------- */
int classDirectorMethods(Node *n);
int classDirectorMethod(Node *n, Node *parent, String *super); int classDirectorMethod(Node *n, Node *parent, String *super);
/* ------------------------------------------------------------ /* ------------------------------------------------------------
@ -1934,10 +1950,27 @@ public:
Printf(f_directors_h," mutable std::map<std::string, bool> inner;\n"); Printf(f_directors_h," mutable std::map<std::string, bool> 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"); Printf(f_directors_h, "};\n\n");
return Language::classDirectorEnd(n); return Language::classDirectorEnd(n);
} }
/* ------------------------------------------------------------ /* ------------------------------------------------------------
* classDirectorDisown() * classDirectorDisown()
* ------------------------------------------------------------ */ * ------------------------------------------------------------ */
@ -2614,7 +2647,7 @@ public:
virtual String *defaultExternalRuntimeFilename() { virtual String *defaultExternalRuntimeFilename() {
return NewString("swigpyrun.h"); return NewString("swigpyrun.h");
} }
}; };
/* --------------------------------------------------------------- /* ---------------------------------------------------------------
@ -2625,6 +2658,11 @@ public:
* *
* ** Moved it here due to internal error on gcc-2.96 ** * ** 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 PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
int is_void = 0; int is_void = 0;
@ -2856,9 +2894,8 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
/* add the method name as a PyString */ /* add the method name as a PyString */
String *pyname = Getattr(n,"sym:name"); String *pyname = Getattr(n,"sym:name");
String *tmp = NewStringf("static swig::PyObject_var swig_method_name = PyString_FromString(\"%s\")",pyname); Wrapper_add_localv(w, "swig_method_index", "const size_t swig_method_index =", NewStringf("%d", director_method_index++), NIL);
Wrapper_add_local(w, "swig_method_name", tmp); Wrapper_add_localv(w, "swig_method_name", "const char * const swig_method_name =", NewStringf("\"%s\"",pyname), NIL);
Delete(tmp);
/* declare method return value /* declare method return value
* if the return value is a reference or const reference, a specialized typemap must * 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 */ /* 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, "swig_set_inner(\"%s\", true);\n", name);
}
Printf(w->code, "if (!swig_get_self()) {\n"); 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, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname);
Printf(w->code, "}\n"); Printf(w->code, "}\n");
Wrapper_add_local(w, "method", "swig::PyObject_var method = 0"); Wrapper_add_local(w, "method", "PyObject* method = 0");
Printf(w->code, "method = PyObject_GetAttr(swig_get_self(), swig_method_name);\n"); Printf(w->code, "method = swig_get_method(swig_method_index, swig_method_name);\n");
Printf(w->code, "if (method == NULL) {\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, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname);
Printf(w->code, "}\n"); Printf(w->code, "}\n");

View file

@ -1082,7 +1082,7 @@ public:
String *symname = Copy(Getattr(n,"sym:name")); String *symname = Copy(Getattr(n,"sym:name"));
SwigType *t = Getattr(n,"type"); SwigType *t = Getattr(n,"type");
ParmList *l = Getattr(n,"parms"); ParmList *l = Getattr(n,"parms");
Node *parent = Getattr(n,"parentNode"); int director_method = 0;
String *tm; String *tm;
int need_result = 0; int need_result = 0;
@ -1220,6 +1220,7 @@ public:
if (!is_smart_pointer()) { if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && !destructor if (/*directorbase &&*/ !constructor && !destructor
&& isVirtual && !Getattr(n,"feature:nodirector")) { && isVirtual && !Getattr(n,"feature:nodirector")) {
director_method = 1;
Wrapper_add_local(f, "director", "Swig::Director *director = 0"); Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n"); Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
Printf(f->code, "if (director && (director->swig_get_self() == self)) director->swig_set_up();\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); 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 */ /* Return value if necessary */
@ -1270,7 +1284,7 @@ public:
Replaceall(tm, "$track","0"); Replaceall(tm, "$track","0");
} }
#if 1
// FIXME: this will not try to unwrap directors returned as non-director // FIXME: this will not try to unwrap directors returned as non-director
// base class pointers! // base class pointers!
@ -1283,21 +1297,26 @@ public:
int is_reference = SwigType_isreference_return(decl); int is_reference = SwigType_isreference_return(decl);
if (is_pointer || is_reference) { if (is_pointer || is_reference) {
String *type = Getattr(n, "type"); String *type = Getattr(n, "type");
Node *parent = Getattr(n,"parentNode");
Node *modname = Getattr(parent, "module"); Node *modname = Getattr(parent, "module");
Node *target = Swig_directormap(modname, type); Node *target = Swig_directormap(modname, type);
if (target) unwrap = true; if (target) unwrap = true;
} }
if (unwrap) { if (unwrap) {
Wrapper_add_local(f, "resultdirector", "Swig::Director *resultdirector = 0"); Wrapper_add_local(f, "director", "Swig::Director *director = 0");
Printf(f->code, "resultdirector = dynamic_cast<Swig::Director *>(result);\n"); Printf(f->code, "director = dynamic_cast<Swig::Director *>(result);\n");
Printf(f->code, "if (resultdirector) {\n"); Printf(f->code, "if (director) {\n");
Printf(f->code, " vresult = resultdirector->swig_get_self();\n"); Printf(f->code, " vresult = director->swig_get_self();\n");
Printf(f->code, "} else {\n"); Printf(f->code, "} else {\n");
Printf(f->code,"%s\n", tm); Printf(f->code,"%s\n", tm);
Printf(f->code, "}\n"); Printf(f->code, "}\n");
director_method = 0;
} else { } else {
Printf(f->code,"%s\n", tm); Printf(f->code,"%s\n", tm);
} }
#else
Printf(f->code,"%s\n", tm);
#endif
} else { } else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s.\n", SwigType_str(t,0)); "Unable to use return type %s.\n", SwigType_str(t,0));
@ -1343,6 +1362,15 @@ public:
Printv(f->code,tm, NIL); 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) */ /* Wrap things up (in a manner of speaking) */
if (need_result) { if (need_result) {
if (current == CONSTRUCTOR_ALLOCATE) { if (current == CONSTRUCTOR_ALLOCATE) {
@ -2218,26 +2246,29 @@ public:
if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0)) if ((tm != 0) && (Len(tm) > 0) && (Strcmp(tm, "1") != 0))
{ {
// Declare a global to hold the depth count // 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 // Function body
Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName); Printf(body->def, "VALUE %s(VALUE data) {\n", bodyName);
Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL); Wrapper_add_localv(body, "args", "Swig::body_args *", "args", "= reinterpret_cast<Swig::body_args *>(data)", NIL);
Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL); Wrapper_add_localv(body, "result", "VALUE", "result", "= Qnil", NIL);
Printf(body->code, "%s++;\n", depthCountName, NIL); Printf(body->code, "%s++;\n", depthCountName, NIL);
Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL); Printv(body->code, "result = rb_funcall2(args->recv, args->id, args->argc, args->argv);\n", NIL);
Printf(body->code, "%s--;\n", depthCountName, NIL); Printf(body->code, "%s--;\n", depthCountName, NIL);
Printv(body->code, "return result;\n", NIL); Printv(body->code, "return result;\n", NIL);
Printv(body->code, "}", 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 // Main code
Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL); Wrapper_add_localv(w, "args", "Swig::body_args", "args", NIL);