add support for multi-inheritance at the python side and performance tunings

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7819 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2005-11-07 12:40:16 +00:00
commit 42277fcfd7
9 changed files with 426 additions and 174 deletions

View file

@ -1,6 +1,69 @@
Version 1.3.28 (unreleased) Version 1.3.28 (unreleased)
=========================== ===========================
11/07/2005: mmatus
[Python] Adding proper support for multi-inheritance in
the python side, ie, if you have two C++ wrapped class, Foo
and Bar, now:
class MyPythonClass(Foo,Bar):
....
will properly work, even with directors, and the
deallocation of Foo.this and Bar.this will follow
correctly. Before, since a class can only have one 'this'
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 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.
- 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.
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 ***
If you overloaded the __del__ method, and call the base
one without a try block, as in
class MyClass(SwigClass):
def __del__(self):
<your code here>
SwigClass.__del__(self)
python could complain that the method SwigClass.__del__ is
undefined. Try to use instead:
def __del__(self):
<your code here>
try: SwigClass.__del__(self)
except: pass
or simply
def __del__(self):
<your code here>
11/02/2005: mmatus 11/02/2005: mmatus
[Python] Adding more fun to STL/STD containers, now you [Python] Adding more fun to STL/STD containers, now you
@ -84,7 +147,7 @@ Version 1.3.28 (unreleased)
In general the sequence method __iter__ will call In general the sequence method __iter__ will call
'iterator()', returning the native C++ iterator, but in 'iterator()', returning the native C++ iterator, but in
maps it will call 'key_iterator()', maintaining maps it will call 'key_iterator()', maintaining
backcompatibilty. backward compatibility.
Hence, for std::maps, you can play then with the native Hence, for std::maps, you can play then with the native
C++ iterator, which value is a (key, value) pair, by C++ iterator, which value is a (key, value) pair, by
@ -153,12 +216,12 @@ Version 1.3.28 (unreleased)
- With this change, and the other ones in the - With this change, and the other ones in the
PySwigObject type, which now carries the thisown and PySwigObject type, which now carries the thisown and
swig_type_info pointer, the generated code shoudl be as swig_type_info pointer, the generated code should be as
fast as boost::Python and/or the other python wrappers fast as boost::Python and/or the other python wrappers
based in pure Python/C API calls. based in pure Python/C API calls.
As a reference, the profiletest_runme.py example, which As a reference, the profiletest_runme.py example, which
does a simple call function many times: does a simple call function many times, such as this code:
import profiletest import profiletest
@ -172,14 +235,20 @@ Version 1.3.28 (unreleased)
produces the following times produces the following times
nomodern modern nomodern modern
swig-1.3.26 25.9s 7.6s swig-1.3.26 19.70s 5.98s
swig-CVS 3.4s 3.3s swig-CVS 0.99s 0.98s
Clearly, there is a large improvement for the python Clearly, there is a large improvement for the python
'nomodern' mode. Still, the 'modern' mode is around 'nomodern' mode. Still, the 'modern' mode is around
twice faster than before. 6 times faster than before. For the same test, but
using the non-shadow version of the module, we get
_profiletest (non-shadow)
swig-1.3.26 0.80s
swig-CVS 0.60s
Hence, now the proxy overhead is almost insignificant.
10/31/2005: mmatus 10/31/2005: mmatus
@ -204,7 +273,7 @@ Version 1.3.28 (unreleased)
print self.this.own() print self.this.own()
>>> True >>> True
- Support for iterartors in STL/STD containers, for example, if you have - Support for iterators in STL/STD containers, for example, if you have
%template<set_string> std::set<std::string>; %template<set_string> std::set<std::string>;
@ -375,7 +444,7 @@ Version 1.3.28 (unreleased)
- uniform the names for the setter and getter methods in - uniform the names for the setter and getter methods in
perl,tcl,ruby and python, so, the attribute.i library perl,tcl,ruby and python, so, the attribute.i library
can work accross them. can work across them.
- see the li_attribute.i test-case or the library file - see the li_attribute.i test-case or the library file
@ -388,7 +457,7 @@ Version 1.3.28 (unreleased)
10/24/2005: mmatus 10/24/2005: mmatus
- Perl uses now the unified typemap libray. - Perl uses now the unified typemap library.
- Changes in ruby to use the $track option in typemaps. - Changes in ruby to use the $track option in typemaps.
@ -439,7 +508,7 @@ Version 1.3.28 (unreleased)
perl5/perlstrings.swg perl5/perlstrings.swg
The rest fo the files, such as carray.i, are mostly one The rest of the files, such as carray.i, are mostly one
line files that include the proper typemap library line files that include the proper typemap library
version. version.

View file

@ -4,9 +4,12 @@
class Foo { class Foo {
public: public:
virtual ~Foo() {} virtual ~Foo() {}
virtual std::string ping() { return "Foo::ping()"; } virtual std::string ping() { return "Foo::ping()"; }
virtual std::string pong() { return "Foo::pong();" + ping(); } virtual std::string pong() { return "Foo::pong();" + ping(); }
static Foo* get_self(Foo *self) {return self;}
}; };
%} %}
@ -18,9 +21,12 @@
class Foo { class Foo {
public: public:
virtual ~Foo() {} virtual ~Foo();
virtual std::string ping() { return "Foo::ping()"; } virtual std::string ping();
virtual std::string pong() { return "Foo::pong();" + ping(); } virtual std::string pong();
static Foo* get_self(Foo *self);
}; };
%{ %{

View file

@ -38,8 +38,8 @@ b = director_basic.Bar(3)
d = director_basic.MyClass() d = director_basic.MyClass()
c = PyClass() c = PyClass()
cc = PyClass.get_self(c) cc = director_basic.MyClass_get_self(c)
dd = PyClass.get_self(d) dd = director_basic.MyClass_get_self(d)
bc = cc.cmethod(b) bc = cc.cmethod(b)
bd = dd.cmethod(b) bd = dd.cmethod(b)
@ -51,3 +51,40 @@ if bc.x != 34:
if bd.x != 16: if bd.x != 16:
raise RuntimeError raise RuntimeError
class PyMulti(director_basic.Foo, director_basic.MyClass):
def __init__(self):
director_basic.Foo.__init__(self)
director_basic.MyClass.__init__(self)
pass
def vmethod(self, b):
b.x += 31
return b
def ping(self):
return "PyFoo::ping()"
a = 0
for i in range(0,100):
pymult = PyMulti()
pymult.pong()
del pymult
pymult = PyMulti()
p1 = director_basic.Foo_get_self(pymult)
p2 = director_basic.MyClass_get_self(pymult)
p1.ping()
p2.vmethod(bc)

View file

@ -3,7 +3,8 @@ from director_finalizer import *
class MyFoo(Foo): class MyFoo(Foo):
def __del__(self): def __del__(self):
self.orStatus(2) self.orStatus(2)
Foo.__del__(self) try: Foo.__del__(self)
except: pass
resetStatus() resetStatus()

View file

@ -4,3 +4,6 @@ a = A()
b = B() b = B()
b.acquire(a) b.acquire(a)
if a.this.own():
raise RuntimeError

View file

@ -1,27 +1,29 @@
import _profiletest
import profiletest import profiletest
a = profiletest.A() a = profiletest.A()
b = profiletest.B() b = profiletest.B()
fn = b.fn
i = 50000 i = 50000
while i: while i:
a = b.fn(a) #1 a = fn(a) #1
a = b.fn(a) #2 a = fn(a) #2
a = b.fn(a) #3 a = fn(a) #3
a = b.fn(a) #4 a = fn(a) #4
a = b.fn(a) #5 a = fn(a) #5
a = b.fn(a) #6 a = fn(a) #6
a = b.fn(a) #7 a = fn(a) #7
a = b.fn(a) #8 a = fn(a) #8
a = b.fn(a) #9 a = fn(a) #9
a = b.fn(a) #10 a = fn(a) #10
a = b.fn(a) #1 a = fn(a) #1
a = b.fn(a) #2 a = fn(a) #2
a = b.fn(a) #3 a = fn(a) #3
a = b.fn(a) #4 a = fn(a) #4
a = b.fn(a) #5 a = fn(a) #5
a = b.fn(a) #6 a = fn(a) #6
a = b.fn(a) #7 a = fn(a) #7
a = b.fn(a) #8 a = fn(a) #8
a = b.fn(a) #9 a = fn(a) #9
a = b.fn(a) #20 a = fn(a) #20
i -= 1 i -= 1

View file

@ -0,0 +1,54 @@
import _profiletest
#import profiletest
pa = _profiletest.new_A()
pb = _profiletest.new_B()
fn = _profiletest.B_fn
destroy = _profiletest.delete_A
i = 50000
a = pa
while i:
a = fn(pb,a) #1
destroy(a)
a = fn(pb,a) #2
destroy(a)
a = fn(pb,a) #3
destroy(a)
a = fn(pb,a) #4
destroy(a)
a = fn(pb,a) #5
destroy(a)
a = fn(pb,a) #6
destroy(a)
a = fn(pb,a) #7
destroy(a)
a = fn(pb,a) #8
destroy(a)
a = fn(pb,a) #9
destroy(a)
a = fn(pb,a) #10
destroy(a)
a = fn(pb,a) #1
destroy(a)
a = fn(pb,a) #2
destroy(a)
a = fn(pb,a) #3
destroy(a)
a = fn(pb,a) #4
destroy(a)
a = fn(pb,a) #5
destroy(a)
a = fn(pb,a) #6
destroy(a)
a = fn(pb,a) #7
destroy(a)
a = fn(pb,a) #8
destroy(a)
a = fn(pb,a) #9
destroy(a)
a = fn(pb,a) #20
destroy(a)
i -= 1
_profiletest.delete_A(pa)
_profiletest.delete_B(pb)

View file

@ -49,7 +49,9 @@ SWIG_Python_ErrorType(int code) {
SWIGINTERNINLINE PyObject * SWIGINTERNINLINE PyObject *
SWIG_Python_ExceptionType(swig_type_info *desc) { SWIG_Python_ExceptionType(swig_type_info *desc) {
return (desc && desc->clientdata ? (PyObject *)(desc->clientdata) : PyExc_RuntimeError); PySwigClientData *data = desc ? (PySwigClientData *) desc->clientdata : 0;
PyObject *klass = data ? data->klass : 0;
return (klass ? klass : PyExc_RuntimeError);
} }
SWIGINTERN void SWIGINTERN void

View file

@ -59,15 +59,19 @@ extern "C" {
/* PySwigObject */ /* PySwigObject */
typedef struct {
PyObject *klass;
PyObject *newargs;
PyObject *destroy;
} PySwigClientData;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
void *ptr; void *ptr;
swig_type_info *ty; swig_type_info *ty;
int own; int own;
PyObject *next;
} PySwigObject; } PySwigObject;
SWIGRUNTIME PyObject * SWIGRUNTIME PyObject *
@ -108,13 +112,14 @@ SWIGRUNTIME PyObject *
PySwigObject_repr(PySwigObject *v) PySwigObject_repr(PySwigObject *v)
{ {
const char *name = SWIG_TypePrettyName(v->ty); const char *name = SWIG_TypePrettyName(v->ty);
PyObject *hex = PySwigObject_hex(v); PyObject *hex = PySwigObject_hex(v);
if (name) { PyObject *repr = PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
return PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
} else {
return PyString_FromFormat("<Swig Object at 0x%s>", PyString_AsString(hex));
}
Py_DECREF(hex); Py_DECREF(hex);
if (v->next) {
PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next);
PyString_ConcatAndDel(&repr,nrep);
}
return repr;
} }
SWIGRUNTIME int SWIGRUNTIME int
@ -130,7 +135,6 @@ PySwigObject_print(PySwigObject *v, FILE *fp, int SWIGUNUSED flags)
} }
} }
SWIGRUNTIME PyObject * SWIGRUNTIME PyObject *
PySwigObject_str(PySwigObject *v) PySwigObject_str(PySwigObject *v)
{ {
@ -158,47 +162,106 @@ PySwigObject_Check(PyObject *op) {
SWIGRUNTIME void SWIGRUNTIME void
PySwigObject_dealloc(PyObject *v) PySwigObject_dealloc(PyObject *v)
{ {
if (PySwigObject_Check(v)) { PySwigObject *sobj = (PySwigObject *) v;
PySwigObject *self = (PySwigObject *) v; PyObject *next = sobj->next;
if (self->own) { if (sobj->own) {
/*
Well, somebody forgot to call delete, or we have a
multi-inheritance case. Hence, we need to call
Class.__destroy__(this).
*/
swig_type_info *ty = sobj->ty;
PySwigClientData *data = ty ? (PySwigClientData *) ty->clientdata : 0;
PyObject *destroy = data ? data->destroy : 0;
if (destroy) {
PyObject *args = PyTuple_New(1);
PyTuple_SetItem(args,0,v);
PyObject_Call(destroy, args, NULL);
Py_DECREF(args);
} else {
const char *name = SWIG_TypePrettyName(ty);
PyObject *wrn = PyString_FromFormat("swig/python detected a memory leak of type '%s'.", name);
PyErr_Warn(PyExc_RuntimeWarning, PyString_AsString(wrn));
Py_DECREF(wrn);
} }
} }
Py_XDECREF(next);
v->ob_type->tp_free(v); v->ob_type->tp_free(v);
} }
SWIGRUNTIME PyObject*
SWIGINTERN PyObject* PySwigObject_append(PyObject* v, PyObject* next)
PySwigObject_disown(PySwigObject *self)
{ {
self->own = 0; PySwigObject *sobj = (PySwigObject *) v;
if (!PySwigObject_Check(next))
return NULL;
sobj->next = next;
Py_INCREF(next);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
SWIGINTERN PyObject* SWIGRUNTIME PyObject*
PySwigObject_acquire(PySwigObject *self) PySwigObject_next(PyObject* v)
{ {
self->own = 1; PySwigObject *sobj = (PySwigObject *) v;
Py_INCREF(Py_None); PyObject *obj = sobj->next ? sobj->next : Py_None;
return Py_None;
}
SWIGINTERN PyObject*
PySwigObject_own(PySwigObject *self)
{
PyObject *obj = self->own ? Py_True : Py_False;
Py_INCREF(obj); Py_INCREF(obj);
return obj; return obj;
} }
SWIGINTERN PyObject*
PySwigObject_disown(PyObject *v)
{
PySwigObject *sobj = (PySwigObject *)v;
sobj->own = 0;
Py_INCREF(Py_None);
return Py_None;
}
SWIGINTERN PyObject*
PySwigObject_acquire(PyObject *v)
{
PySwigObject *sobj = (PySwigObject *)v;
sobj->own = 1;
Py_INCREF(Py_None);
return Py_None;
}
SWIGINTERN PyObject*
PySwigObject_own(PyObject *v, PyObject *args)
{
PyObject *val = 0;
if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) {
return NULL;
} else {
PySwigObject *sobj = (PySwigObject *)v;
PyObject *obj = sobj->own ? Py_True : Py_False;
if (val) {
if (PyObject_IsTrue(val)) {
PySwigObject_acquire(v);
} else {
PySwigObject_disown(v);
}
}
Py_INCREF(obj);
return obj;
}
}
SWIGRUNTIME PyTypeObject* SWIGRUNTIME PyTypeObject*
PySwigObject_type(void) { PySwigObject_type(void) {
static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
static PyMethodDef static PyMethodDef
swigobject_methods[] = { swigobject_methods[] = {
{"disown", (PyCFunction)PySwigObject_disown, METH_NOARGS, "release ownership of the pointer"}, {"disown", (PyCFunction)PySwigObject_disown, METH_NOARGS, "releases ownership of the pointer"},
{"acquire", (PyCFunction)PySwigObject_acquire, METH_NOARGS, "aquire ownership of the pointer"}, {"acquire", (PyCFunction)PySwigObject_acquire, METH_NOARGS, "aquires ownership of the pointer"},
{"own", (PyCFunction)PySwigObject_own, METH_NOARGS, "return ownership status of the pointer"}, {"own", (PyCFunction)PySwigObject_own, METH_VARARGS, "returns/sets ownership of the pointer"},
{"append", (PyCFunction)PySwigObject_append, METH_O, "appends another 'this' object"},
{"next", (PyCFunction)PySwigObject_next, METH_NOARGS, "returns the next 'this' object"},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -312,13 +375,14 @@ PySwigObject_type(void) {
SWIGRUNTIME PyObject * SWIGRUNTIME PyObject *
PySwigObject_New(void *ptr, swig_type_info *ty, int own) PySwigObject_New(void *ptr, swig_type_info *ty, int own)
{ {
PySwigObject *self = PyObject_NEW(PySwigObject, PySwigObject_type()); PySwigObject *sobj = PyObject_NEW(PySwigObject, PySwigObject_type());
if (self) { if (sobj) {
self->ptr = ptr; sobj->ptr = ptr;
self->ty = ty; sobj->ty = ty;
self->own = own; sobj->own = own;
sobj->next = 0;
} }
return (PyObject *)self; return (PyObject *)sobj;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -390,8 +454,8 @@ SWIGRUNTIME void
PySwigPacked_dealloc(PyObject *v) PySwigPacked_dealloc(PyObject *v)
{ {
if (PySwigPacked_Check(v)) { if (PySwigPacked_Check(v)) {
PySwigPacked *self = (PySwigPacked *) v; PySwigPacked *sobj = (PySwigPacked *) v;
free(self->pack); free(sobj->pack);
} }
v->ob_type->tp_free(v); v->ob_type->tp_free(v);
} }
@ -476,17 +540,17 @@ PySwigPacked_type(void) {
SWIGRUNTIME PyObject * SWIGRUNTIME PyObject *
PySwigPacked_New(void *ptr, size_t size, swig_type_info *ty) PySwigPacked_New(void *ptr, size_t size, swig_type_info *ty)
{ {
PySwigPacked *self = PyObject_NEW(PySwigPacked, PySwigPacked_type()); PySwigPacked *sobj = PyObject_NEW(PySwigPacked, PySwigPacked_type());
if (self == NULL) { if (sobj == NULL) {
return NULL; return NULL;
} else { } else {
void *pack = malloc(size); void *pack = malloc(size);
if (pack) { if (pack) {
memcpy(pack, ptr, size); memcpy(pack, ptr, size);
self->pack = pack; sobj->pack = pack;
self->ty = ty; sobj->ty = ty;
self->size = size; sobj->size = size;
return (PyObject *) self; return (PyObject *) sobj;
} }
return NULL; return NULL;
} }
@ -496,10 +560,10 @@ SWIGRUNTIMEINLINE swig_type_info *
PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size) PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
{ {
if (PySwigPacked_Check(obj)) { if (PySwigPacked_Check(obj)) {
PySwigPacked *self = (PySwigPacked *)obj; PySwigPacked *sobj = (PySwigPacked *)obj;
if (self->size != size) return 0; if (sobj->size != size) return 0;
memcpy(ptr, self->pack, size); memcpy(ptr, sobj->pack, size);
return self->ty; return sobj->ty;
} else { } else {
return 0; return 0;
} }
@ -519,24 +583,13 @@ SWIG_This()
/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ /* #define SWIG_PYTHON_SLOW_GETSET_THIS */
/* Convert a pointer value */ SWIGRUNTIMEINLINE PySwigObject *
SWIGRUNTIME int SWIG_Python_GetSwigThis(PyObject *pyobj)
SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) { {
swig_type_info *to = 0; if (PySwigObject_Check(pyobj)) {
const char *desc = 0; return (PySwigObject *) pyobj;
int newref = 0; } else {
PyObject *pyobj = 0; PyObject *obj = 0;
void *vptr = 0;
PySwigObject *sobj = 0;
if (!obj) return SWIG_ERROR;
if (obj == Py_None) {
*ptr = 0;
return SWIG_OK;
}
if (!(PySwigObject_Check(obj))) {
pyobj = obj;
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS #ifndef SWIG_PYTHON_SLOW_GETSET_THIS
if (PyInstance_Check(pyobj)) { if (PyInstance_Check(pyobj)) {
obj = _PyInstance_Lookup(pyobj, SWIG_This()); obj = _PyInstance_Lookup(pyobj, SWIG_This());
@ -549,45 +602,60 @@ SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags)
obj = PyObject_GetAttr(pyobj,SWIG_This()); obj = PyObject_GetAttr(pyobj,SWIG_This());
} }
} }
Py_XINCREF(obj);
#else #else
obj = PyObject_GetAttr(pyobj,SWIG_This()); obj = PyObject_GetAttr(pyobj,SWIG_This());
#endif #endif
if (!obj) goto type_error; if (PyErr_Occurred()) {
if (!PySwigObject_Check(obj)) { obj = 0;
Py_DECREF(obj); PyErr_Clear();
goto type_error;
} }
newref = 1; return obj && PySwigObject_Check(obj) ? (PySwigObject *) obj : 0;
}
sobj = (PySwigObject *) obj;
vptr = sobj->ptr;
to = sobj->ty;
desc = (const char *) to->name;
if (newref) { newref = 0; Py_DECREF(obj); }
if (ty) {
if (to == ty) {
/* no type cast needed */
*ptr = vptr;
} else {
swig_cast_info *tc = SWIG_TypeCheck(desc,ty);
if (!tc) goto type_error;
*ptr = SWIG_TypeCast(tc,vptr);
}
} else {
*ptr = vptr;
} }
if ((pyobj) && (flags & SWIG_POINTER_DISOWN)) {
sobj->own = 0;
}
return SWIG_OK;
type_error:
PyErr_Clear();
return SWIG_ERROR;
} }
/* Convert a pointer value */
SWIGRUNTIME int
SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
if (!obj) return SWIG_ERROR;
if (obj == Py_None) {
*ptr = 0;
return SWIG_OK;
} else {
PySwigObject *sobj = SWIG_Python_GetSwigThis(obj);
while (sobj) {
void *vptr = sobj->ptr;
if (ty) {
swig_type_info *to = sobj->ty;
if (to == ty) {
/* no type cast needed */
*ptr = vptr;
break;
} else {
swig_cast_info *tc = SWIG_TypeCheck(to->name,ty);
if (!tc) {
sobj = (PySwigObject *)sobj->next;
} else {
*ptr = SWIG_TypeCast(tc,vptr);
break;
}
}
} else {
*ptr = vptr;
break;
}
}
if (sobj) {
if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0;
}
return SWIG_OK;
} else {
return SWIG_ERROR;
}
}
}
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)) {
@ -640,19 +708,34 @@ SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *t
* Create a new pointer object * Create a new pointer object
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
#define SWIG_NewClientData(obj) SWIG_Python_NewClientData(obj) #define SWIG_NewClientData(obj) PySwigClientData_New(obj)
SWIGRUNTIMEINLINE void * SWIGRUNTIMEINLINE void *
SWIG_Python_NewClientData(PyObject* obj) PySwigClientData_New(PyObject* obj)
{ {
PySwigClientData *data = (PySwigClientData *)malloc(sizeof(PySwigClientData));
data->klass = 0;
data->newargs = 0;
data->destroy = 0;
if (PyClass_Check(obj)) { if (PyClass_Check(obj)) {
Py_INCREF(obj); data->klass = obj;
return obj; data->newargs = obj;
Py_INCREF(data->newargs);
} else { } else {
PyObject *args = PyTuple_New(1); data->klass = obj;
PyTuple_SetItem(args, 0, obj); data->newargs = PyTuple_New(1);
return args; PyTuple_SetItem(data->newargs, 0, obj);
} }
if (data->klass) {
static PyObject* SWIG_STATIC_POINTER(destroystr) = PyString_FromString("__destroy__");
data->destroy = PyObject_GetAttr(data->klass, destroystr);
if (PyErr_Occurred()) {
PyErr_Clear();
data->destroy = 0;
}
}
return data;
} }
/* /*
@ -660,15 +743,14 @@ SWIG_Python_NewClientData(PyObject* obj)
and set the 'this' attribute. and set the 'this' attribute.
*/ */
SWIGRUNTIMEINLINE PyObject*
SWIGRUNTIME PyObject* SWIG_Python_NewShadowInstance(PySwigClientData *data, PyObject *swig_this)
SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
{ {
PyObject *inst = 0; PyObject *inst = 0;
if (!PyClass_Check(obj)) { if (!PyClass_Check(data->klass)) {
static PyObject* SWIG_STATIC_POINTER(fnew) = static PyObject* SWIG_STATIC_POINTER(fnew) =
PyObject_GetAttrString((PyObject*)&PyBaseObject_Type, "__new__"); PyObject_GetAttrString((PyObject*)&PyBaseObject_Type, "__new__");
inst = PyObject_Call(fnew, obj, NULL); inst = PyObject_Call(fnew, data->newargs, NULL);
if (inst) { if (inst) {
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS #ifndef SWIG_PYTHON_SLOW_GETSET_THIS
PyObject **dictptr = _PyObject_GetDictPtr(inst); PyObject **dictptr = _PyObject_GetDictPtr(inst);
@ -677,17 +759,17 @@ SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
if (dict == NULL) { if (dict == NULL) {
dict = PyDict_New(); dict = PyDict_New();
*dictptr = dict; *dictptr = dict;
PyDict_SetItem(dict, SWIG_This(), swig_this);
} }
PyDict_SetItem(dict, SWIG_This(), swig_this); }
}
#else #else
PyObject_SetAttr(inst, SWIG_This(), swig_this); PyObject_SetAttr(inst, SWIG_This(), swig_this);
#endif #endif
} }
} else { } else {
PyObject *dict = PyDict_New(); PyObject *dict = PyDict_New();
PyDict_SetItem(dict,SWIG_This(), swig_this); PyDict_SetItem(dict, SWIG_This(), swig_this);
inst = PyInstance_NewRaw(obj, dict); inst = PyInstance_NewRaw(data->newargs, dict);
Py_DECREF(dict); Py_DECREF(dict);
} }
return inst; return inst;
@ -696,30 +778,26 @@ SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
SWIGRUNTIME PyObject * SWIGRUNTIME PyObject *
SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) { SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
PyObject *robj = 0;
int own = (flags & SWIG_POINTER_OWN);
int shadow = !(flags & SWIG_POINTER_NOSHADOW);
if (!type) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
}
return robj;
}
if (!ptr) { if (!ptr) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} } else if (!type) {
if (!PyErr_Occurred()) {
robj = PySwigObject_New((void *) ptr, type, own); PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
if (!robj || (robj == Py_None)) return robj;
if (shadow && type->clientdata) {
PyObject *inst = SWIG_Python_NewShadowInstance((PyObject *)type->clientdata, robj);
if (inst) {
Py_DECREF(robj);
robj = inst;
} }
return NULL;
} else {
PyObject *robj = PySwigObject_New((void *) ptr, type, (flags & SWIG_POINTER_OWN));
PySwigClientData *clientdata = (PySwigClientData *)type->clientdata;
if (clientdata && !(flags & SWIG_POINTER_NOSHADOW)) {
PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj);
if (inst) {
Py_DECREF(robj);
robj = inst;
}
}
return robj;
} }
return robj;
} }
/* Create a new array object */ /* Create a new array object */