%implicitconv will now accept None where the implicit conversion takes a C/C++ pointer.

Problem highlighted by Bo Peng on the swig-user mailing list. SF patch #230.
This commit is contained in:
William S Fulton 2013-08-16 08:12:09 +01:00
commit 1cc735df5e
4 changed files with 79 additions and 5 deletions

View file

@ -8,6 +8,10 @@ Version 2.0.11 (in progress)
2013-08-23: olly 2013-08-23: olly
[Python] Fix clang++ warning in generated wrapper code. [Python] Fix clang++ warning in generated wrapper code.
2013-08-16: wsfulton
[Python] %implicitconv will now accept None where the implicit conversion takes a C/C++ pointer.
Problem highlighted by Bo Peng. Closes SF patch #230.
2013-08-07: wsfulton 2013-08-07: wsfulton
[Python] SF Patch #326 from Kris Thielemans - Remove SwigPyObject_print and SwigPyObject_str and [Python] SF Patch #326 from Kris Thielemans - Remove SwigPyObject_print and SwigPyObject_str and
make the generated wrapper use the default python implementations, which will fall back to repr make the generated wrapper use the default python implementations, which will fall back to repr

View file

@ -46,7 +46,6 @@
Foo(double){ ii = 2;} Foo(double){ ii = 2;}
explicit Foo(char *s){ii = 3;} explicit Foo(char *s){ii = 3;}
Foo(const Foo& f){ ii = f.ii;} Foo(const Foo& f){ ii = f.ii;}
}; };
struct Bar struct Bar
@ -57,11 +56,31 @@
Bar(const Foo& ff){ ii = ff.ii;} Bar(const Foo& ff){ ii = ff.ii;}
}; };
int get_b(const Bar&b) { return b.ii; } int get_b(const Bar&b) { return b.ii; }
Foo foo; Foo foo;
} }
%template(A_int) A_T<int>; %template(A_int) A_T<int>;
/****************** None handling *********************/
%inline
{
struct BB {};
struct AA
{
int ii;
AA(int i) { ii = 1; }
AA(double d) { ii = 2; }
AA(const B* b) { ii = 3; }
explicit AA(char *s) { ii = 4; }
AA(const BB& b) { ii = 5; }
int get() const { return ii; }
};
int get_AA_val(AA a) { return a.ii; }
int get_AA_ref(const AA& a) { return a.ii; }
}

View file

@ -11,6 +11,14 @@ check(1, A(1).get())
check(2, A(1.0).get()) check(2, A(1.0).get())
check(3, A(B()).get()) check(3, A(B()).get())
check(4, A("hello").get()) check(4, A("hello").get())
try:
check(3, A(None).get())
raise RuntimeError
except ValueError:
# ValueError: invalid null reference in method 'new_A', argument 1 of type 'B const &'
# Arguably A(char *) should be chosen, but there is a bug to do with None passed to methods overloaded by value,
# references and pointers to different types, where pointers ought to be given a slightly higher precedence.
pass
check(1, get(1)) check(1, get(1))
check(2, get(1.0)) check(2, get(1.0))
@ -71,3 +79,38 @@ try:
except TypeError: except TypeError:
pass pass
#### Class testing None ####
# No implicit conversion
check(1, AA(1).get())
check(2, AA(1.0).get())
check(3, AA(B()).get())
check(3, AA(None).get())
check(4, AA("hello").get())
check(5, AA(BB()).get())
check(1, get_AA_val(1))
check(2, get_AA_val(1.0))
check(3, get_AA_val(B()))
check(3, get_AA_val(None))
check(5, get_AA_val(BB()))
# Explicit constructor:
try:
check(4, get_AA_val("hello"))
raise RuntimeError
except TypeError:
pass
check(1, get_AA_ref(1))
check(2, get_AA_ref(1.0))
check(3, get_AA_ref(B()))
check(3, get_AA_ref(None))
check(5, get_AA_ref(BB()))
# Explicit constructor:
try:
check(4, get_AA_ref("hello"))
raise RuntimeError
except TypeError:
pass

View file

@ -1128,10 +1128,11 @@ SWIGRUNTIME int
SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
int res; int res;
SwigPyObject *sobj; SwigPyObject *sobj;
int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
if (!obj) if (!obj)
return SWIG_ERROR; return SWIG_ERROR;
if (obj == Py_None) { if (obj == Py_None && !implicit_conv) {
if (ptr) if (ptr)
*ptr = 0; *ptr = 0;
return SWIG_OK; return SWIG_OK;
@ -1180,7 +1181,7 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
} }
res = SWIG_OK; res = SWIG_OK;
} else { } else {
if (flags & SWIG_POINTER_IMPLICIT_CONV) { if (implicit_conv) {
SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
if (data && !data->implicitconv) { if (data && !data->implicitconv) {
PyObject *klass = data->klass; PyObject *klass = data->klass;
@ -1215,6 +1216,13 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
} }
} }
} }
if (!SWIG_IsOK(res) && obj == Py_None) {
if (ptr)
*ptr = 0;
if (PyErr_Occurred())
PyErr_Clear();
res = SWIG_OK;
}
} }
return res; return res;
} }