summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2013-08-16 08:12:09 +0100
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2013-08-28 20:28:15 +0100
commit1cc735df5e087edc2ac189b39a1ccb12ed304a13 (patch)
tree91e1e5b7f3d7c275ba2bd457c7f32f3a93183054
parent628b4710e5309379475f55c95a42e1cf21c9be87 (diff)
downloadswig-1cc735df5e087edc2ac189b39a1ccb12ed304a13.tar.gz
%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.
-rw-r--r--CHANGES.current4
-rw-r--r--Examples/test-suite/implicittest.i25
-rw-r--r--Examples/test-suite/python/implicittest_runme.py43
-rw-r--r--Lib/python/pyrun.swg12
4 files changed, 79 insertions, 5 deletions
diff --git a/CHANGES.current b/CHANGES.current
index 584d5c3a2..f87f7ef70 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -8,6 +8,10 @@ Version 2.0.11 (in progress)
2013-08-23: olly
[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
[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
diff --git a/Examples/test-suite/implicittest.i b/Examples/test-suite/implicittest.i
index e07adc5cc..10f901710 100644
--- a/Examples/test-suite/implicittest.i
+++ b/Examples/test-suite/implicittest.i
@@ -46,7 +46,6 @@
Foo(double){ ii = 2;}
explicit Foo(char *s){ii = 3;}
Foo(const Foo& f){ ii = f.ii;}
-
};
struct Bar
@@ -57,11 +56,31 @@
Bar(const Foo& ff){ ii = ff.ii;}
};
-
int get_b(const Bar&b) { return b.ii; }
Foo foo;
-
}
%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; }
+}
diff --git a/Examples/test-suite/python/implicittest_runme.py b/Examples/test-suite/python/implicittest_runme.py
index 4200543c4..5644555df 100644
--- a/Examples/test-suite/python/implicittest_runme.py
+++ b/Examples/test-suite/python/implicittest_runme.py
@@ -11,6 +11,14 @@ check(1, A(1).get())
check(2, A(1.0).get())
check(3, A(B()).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(2, get(1.0))
@@ -71,3 +79,38 @@ try:
except TypeError:
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
diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg
index 273c82302..b077fad32 100644
--- a/Lib/python/pyrun.swg
+++ b/Lib/python/pyrun.swg
@@ -1128,10 +1128,11 @@ SWIGRUNTIME int
SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) {
int res;
SwigPyObject *sobj;
+ int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0;
if (!obj)
return SWIG_ERROR;
- if (obj == Py_None) {
+ if (obj == Py_None && !implicit_conv) {
if (ptr)
*ptr = 0;
return SWIG_OK;
@@ -1180,7 +1181,7 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
}
res = SWIG_OK;
} else {
- if (flags & SWIG_POINTER_IMPLICIT_CONV) {
+ if (implicit_conv) {
SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;
if (data && !data->implicitconv) {
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;
}