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)
===========================
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
[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
'iterator()', returning the native C++ iterator, but in
maps it will call 'key_iterator()', maintaining
backcompatibilty.
backward compatibility.
Hence, for std::maps, you can play then with the native
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
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
based in pure Python/C API calls.
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
@ -172,14 +235,20 @@ Version 1.3.28 (unreleased)
produces the following times
nomodern modern
swig-1.3.26 25.9s 7.6s
swig-CVS 3.4s 3.3s
swig-1.3.26 19.70s 5.98s
swig-CVS 0.99s 0.98s
Clearly, there is a large improvement for the python
'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
@ -204,7 +273,7 @@ Version 1.3.28 (unreleased)
print self.this.own()
>>> 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>;
@ -375,7 +444,7 @@ Version 1.3.28 (unreleased)
- uniform the names for the setter and getter methods in
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
@ -388,7 +457,7 @@ Version 1.3.28 (unreleased)
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.
@ -439,7 +508,7 @@ Version 1.3.28 (unreleased)
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
version.

View file

@ -4,9 +4,12 @@
class Foo {
public:
virtual ~Foo() {}
virtual std::string ping() { return "Foo::ping()"; }
virtual std::string pong() { return "Foo::pong();" + ping(); }
virtual ~Foo() {}
virtual std::string ping() { return "Foo::ping()"; }
virtual std::string pong() { return "Foo::pong();" + ping(); }
static Foo* get_self(Foo *self) {return self;}
};
%}
@ -18,9 +21,12 @@
class Foo {
public:
virtual ~Foo() {}
virtual std::string ping() { return "Foo::ping()"; }
virtual std::string pong() { return "Foo::pong();" + ping(); }
virtual ~Foo();
virtual std::string 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()
c = PyClass()
cc = PyClass.get_self(c)
dd = PyClass.get_self(d)
cc = director_basic.MyClass_get_self(c)
dd = director_basic.MyClass_get_self(d)
bc = cc.cmethod(b)
bd = dd.cmethod(b)
@ -51,3 +51,40 @@ if bc.x != 34:
if bd.x != 16:
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):
def __del__(self):
self.orStatus(2)
Foo.__del__(self)
try: Foo.__del__(self)
except: pass
resetStatus()

View file

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

View file

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

View file

@ -59,15 +59,19 @@ extern "C" {
/* PySwigObject */
typedef struct {
PyObject *klass;
PyObject *newargs;
PyObject *destroy;
} PySwigClientData;
typedef struct {
PyObject_HEAD
void *ptr;
swig_type_info *ty;
int own;
PyObject *next;
} PySwigObject;
SWIGRUNTIME PyObject *
@ -108,13 +112,14 @@ SWIGRUNTIME PyObject *
PySwigObject_repr(PySwigObject *v)
{
const char *name = SWIG_TypePrettyName(v->ty);
PyObject *hex = PySwigObject_hex(v);
if (name) {
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));
}
PyObject *hex = PySwigObject_hex(v);
PyObject *repr = PyString_FromFormat("<Swig Object of type '%s' at 0x%s>", name, PyString_AsString(hex));
Py_DECREF(hex);
if (v->next) {
PyObject *nrep = PySwigObject_repr((PySwigObject *)v->next);
PyString_ConcatAndDel(&repr,nrep);
}
return repr;
}
SWIGRUNTIME int
@ -130,7 +135,6 @@ PySwigObject_print(PySwigObject *v, FILE *fp, int SWIGUNUSED flags)
}
}
SWIGRUNTIME PyObject *
PySwigObject_str(PySwigObject *v)
{
@ -158,47 +162,106 @@ PySwigObject_Check(PyObject *op) {
SWIGRUNTIME void
PySwigObject_dealloc(PyObject *v)
{
if (PySwigObject_Check(v)) {
PySwigObject *self = (PySwigObject *) v;
if (self->own) {
PySwigObject *sobj = (PySwigObject *) v;
PyObject *next = sobj->next;
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);
}
SWIGINTERN PyObject*
PySwigObject_disown(PySwigObject *self)
SWIGRUNTIME PyObject*
PySwigObject_append(PyObject* v, PyObject* next)
{
self->own = 0;
PySwigObject *sobj = (PySwigObject *) v;
if (!PySwigObject_Check(next))
return NULL;
sobj->next = next;
Py_INCREF(next);
Py_INCREF(Py_None);
return Py_None;
}
SWIGINTERN PyObject*
PySwigObject_acquire(PySwigObject *self)
SWIGRUNTIME PyObject*
PySwigObject_next(PyObject* v)
{
self->own = 1;
Py_INCREF(Py_None);
return Py_None;
}
PySwigObject *sobj = (PySwigObject *) v;
PyObject *obj = sobj->next ? sobj->next : Py_None;
SWIGINTERN PyObject*
PySwigObject_own(PySwigObject *self)
{
PyObject *obj = self->own ? Py_True : Py_False;
Py_INCREF(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*
PySwigObject_type(void) {
static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer";
static PyMethodDef
swigobject_methods[] = {
{"disown", (PyCFunction)PySwigObject_disown, METH_NOARGS, "release ownership of the pointer"},
{"acquire", (PyCFunction)PySwigObject_acquire, METH_NOARGS, "aquire ownership of the pointer"},
{"own", (PyCFunction)PySwigObject_own, METH_NOARGS, "return ownership status of the pointer"},
{"disown", (PyCFunction)PySwigObject_disown, METH_NOARGS, "releases ownership of the pointer"},
{"acquire", (PyCFunction)PySwigObject_acquire, METH_NOARGS, "aquires ownership 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}
};
@ -312,13 +375,14 @@ PySwigObject_type(void) {
SWIGRUNTIME PyObject *
PySwigObject_New(void *ptr, swig_type_info *ty, int own)
{
PySwigObject *self = PyObject_NEW(PySwigObject, PySwigObject_type());
if (self) {
self->ptr = ptr;
self->ty = ty;
self->own = own;
PySwigObject *sobj = PyObject_NEW(PySwigObject, PySwigObject_type());
if (sobj) {
sobj->ptr = ptr;
sobj->ty = ty;
sobj->own = own;
sobj->next = 0;
}
return (PyObject *)self;
return (PyObject *)sobj;
}
/* -----------------------------------------------------------------------------
@ -390,8 +454,8 @@ SWIGRUNTIME void
PySwigPacked_dealloc(PyObject *v)
{
if (PySwigPacked_Check(v)) {
PySwigPacked *self = (PySwigPacked *) v;
free(self->pack);
PySwigPacked *sobj = (PySwigPacked *) v;
free(sobj->pack);
}
v->ob_type->tp_free(v);
}
@ -476,17 +540,17 @@ PySwigPacked_type(void) {
SWIGRUNTIME PyObject *
PySwigPacked_New(void *ptr, size_t size, swig_type_info *ty)
{
PySwigPacked *self = PyObject_NEW(PySwigPacked, PySwigPacked_type());
if (self == NULL) {
PySwigPacked *sobj = PyObject_NEW(PySwigPacked, PySwigPacked_type());
if (sobj == NULL) {
return NULL;
} else {
void *pack = malloc(size);
if (pack) {
memcpy(pack, ptr, size);
self->pack = pack;
self->ty = ty;
self->size = size;
return (PyObject *) self;
sobj->pack = pack;
sobj->ty = ty;
sobj->size = size;
return (PyObject *) sobj;
}
return NULL;
}
@ -496,10 +560,10 @@ SWIGRUNTIMEINLINE swig_type_info *
PySwigPacked_UnpackData(PyObject *obj, void *ptr, size_t size)
{
if (PySwigPacked_Check(obj)) {
PySwigPacked *self = (PySwigPacked *)obj;
if (self->size != size) return 0;
memcpy(ptr, self->pack, size);
return self->ty;
PySwigPacked *sobj = (PySwigPacked *)obj;
if (sobj->size != size) return 0;
memcpy(ptr, sobj->pack, size);
return sobj->ty;
} else {
return 0;
}
@ -519,24 +583,13 @@ SWIG_This()
/* #define SWIG_PYTHON_SLOW_GETSET_THIS */
/* Convert a pointer value */
SWIGRUNTIME int
SWIG_Python_ConvertPtr(PyObject *obj, void **ptr, swig_type_info *ty, int flags) {
swig_type_info *to = 0;
const char *desc = 0;
int newref = 0;
PyObject *pyobj = 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;
SWIGRUNTIMEINLINE PySwigObject *
SWIG_Python_GetSwigThis(PyObject *pyobj)
{
if (PySwigObject_Check(pyobj)) {
return (PySwigObject *) pyobj;
} else {
PyObject *obj = 0;
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS
if (PyInstance_Check(pyobj)) {
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());
}
}
Py_XINCREF(obj);
#else
obj = PyObject_GetAttr(pyobj,SWIG_This());
#endif
if (!obj) goto type_error;
if (!PySwigObject_Check(obj)) {
Py_DECREF(obj);
goto type_error;
#endif
if (PyErr_Occurred()) {
obj = 0;
PyErr_Clear();
}
newref = 1;
}
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;
return obj && PySwigObject_Check(obj) ? (PySwigObject *) obj : 0;
}
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
SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) {
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
* ----------------------------------------------------------------------------- */
#define SWIG_NewClientData(obj) SWIG_Python_NewClientData(obj)
#define SWIG_NewClientData(obj) PySwigClientData_New(obj)
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)) {
Py_INCREF(obj);
return obj;
data->klass = obj;
data->newargs = obj;
Py_INCREF(data->newargs);
} else {
PyObject *args = PyTuple_New(1);
PyTuple_SetItem(args, 0, obj);
return args;
data->klass = obj;
data->newargs = PyTuple_New(1);
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.
*/
SWIGRUNTIME PyObject*
SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
SWIGRUNTIMEINLINE PyObject*
SWIG_Python_NewShadowInstance(PySwigClientData *data, PyObject *swig_this)
{
PyObject *inst = 0;
if (!PyClass_Check(obj)) {
if (!PyClass_Check(data->klass)) {
static PyObject* SWIG_STATIC_POINTER(fnew) =
PyObject_GetAttrString((PyObject*)&PyBaseObject_Type, "__new__");
inst = PyObject_Call(fnew, obj, NULL);
inst = PyObject_Call(fnew, data->newargs, NULL);
if (inst) {
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS
PyObject **dictptr = _PyObject_GetDictPtr(inst);
@ -677,17 +759,17 @@ SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
if (dict == NULL) {
dict = PyDict_New();
*dictptr = dict;
PyDict_SetItem(dict, SWIG_This(), swig_this);
}
PyDict_SetItem(dict, SWIG_This(), swig_this);
}
}
#else
PyObject_SetAttr(inst, SWIG_This(), swig_this);
#endif
}
} else {
PyObject *dict = PyDict_New();
PyDict_SetItem(dict,SWIG_This(), swig_this);
inst = PyInstance_NewRaw(obj, dict);
PyDict_SetItem(dict, SWIG_This(), swig_this);
inst = PyInstance_NewRaw(data->newargs, dict);
Py_DECREF(dict);
}
return inst;
@ -696,30 +778,26 @@ SWIG_Python_NewShadowInstance(PyObject *obj, PyObject *swig_this)
SWIGRUNTIME PyObject *
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) {
Py_INCREF(Py_None);
return Py_None;
}
robj = PySwigObject_New((void *) ptr, type, own);
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;
} else if (!type) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
}
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 */