diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2013-08-16 08:12:09 +0100 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2013-08-28 20:28:15 +0100 |
commit | 1cc735df5e087edc2ac189b39a1ccb12ed304a13 (patch) | |
tree | 91e1e5b7f3d7c275ba2bd457c7f32f3a93183054 | |
parent | 628b4710e5309379475f55c95a42e1cf21c9be87 (diff) | |
download | swig-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.current | 4 | ||||
-rw-r--r-- | Examples/test-suite/implicittest.i | 25 | ||||
-rw-r--r-- | Examples/test-suite/python/implicittest_runme.py | 43 | ||||
-rw-r--r-- | Lib/python/pyrun.swg | 12 |
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; } |