From 5a76bc68fc1b3491255d2d6cd8c49c982c17a2bb Mon Sep 17 00:00:00 2001 From: Marcelo Matus Date: Fri, 23 Dec 2005 09:22:17 +0000 Subject: [PATCH] add castmode in python and cleaning the castdispatch mechanism git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@8051 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/CHANGES.current | 40 +++++ .../test-suite/perl5/overload_simple_runme.pl | 11 +- SWIG/Examples/test-suite/python/Makefile.in | 2 + .../test-suite/python/overload_simple_cast.i | 4 + .../python/overload_simple_cast_runme.py | 165 ++++++++++++++++++ SWIG/Lib/perl5/perlprimtypes.swg | 95 +++------- SWIG/Lib/python/pycomplex.swg | 14 +- SWIG/Lib/python/pyprimtypes.swg | 129 +++++++++++++- SWIG/Lib/python/pystdcommon.swg | 4 +- SWIG/Lib/swigerrors.swg | 1 + SWIG/Lib/swigrun.swg | 13 +- SWIG/Lib/typemaps/inoutlist.swg | 4 +- SWIG/Lib/typemaps/primtypes.swg | 34 ++++ SWIG/Lib/typemaps/valtypes.swg | 4 +- SWIG/Source/Modules/overload.cxx | 10 +- SWIG/Source/Modules/python.cxx | 32 +++- 16 files changed, 461 insertions(+), 101 deletions(-) create mode 100644 SWIG/Examples/test-suite/python/overload_simple_cast.i create mode 100644 SWIG/Examples/test-suite/python/overload_simple_cast_runme.py diff --git a/SWIG/CHANGES.current b/SWIG/CHANGES.current index c337a8781..0b3779bd2 100644 --- a/SWIG/CHANGES.current +++ b/SWIG/CHANGES.current @@ -1,6 +1,46 @@ Version 1.3.28 (unreleased). =========================== +12/23/2005: mmatus + [python] Add the castmode that allows the python + type casting to occurr. + + For example, if you have 'int foo(int)', now + + class Ai(): + def __init__(self,x): + self.x = x + def __int__(self): + return self.x + + foo(1) // Ok + foo(1.0) // Ok + foo(1.3) // Error + a = Ai(4) + foo(ai) // Ok + + The castmode, which can be enable either with the + '-castmode' option or the %module("castmode") option, uses + the new cast/rank dispatch mechanism. Hence, now if you + have 'int foo(int); int foo(double);', the following works + as expected: + + foo(1) -> foo(int) + foo(1.0) -> foo(double) + ai = Ai(4) + foo(ai) -> foo(int) + + Note1: the 'castmode' could disrupt some specialized + typemaps. In particular, the "implicit.i" library seems to + have problem with the castmode. But besides that one, the + entire test-suite compiles fine with and without the + castmode. + + Note2: the castmode disables the -fatdispatch option. + + See the file overload_dispatch_cast_runme.py file for + new cases and examples. + 12/22/2005: mmatus Add the cast and rank mechanism to dispatch overloading functions. The UTF supports it now, but for each language diff --git a/SWIG/Examples/test-suite/perl5/overload_simple_runme.pl b/SWIG/Examples/test-suite/perl5/overload_simple_runme.pl index 645a6e5fe..0335124f4 100644 --- a/SWIG/Examples/test-suite/perl5/overload_simple_runme.pl +++ b/SWIG/Examples/test-suite/perl5/overload_simple_runme.pl @@ -4,9 +4,6 @@ $f = new overload_simple::Foo(); $b = new overload_simple::Bar(); $v = overload_simple::malloc_void(32); -# -# 'simple' dispatch (no overload) of int and double arguments -# # # Silence warnings about bad types @@ -40,6 +37,10 @@ if (!$@) { # $DOWARN =1; +# +# 'simple' dispatch (no overload) of int and double arguments +# + if (!(overload_simple::fint(3) eq "fint:int")) { die("fint(int)"); } @@ -159,6 +160,8 @@ if (!($s->foo(3.0) eq "foo:double")) { } if (!($s->foo("hello") eq "foo:char *")) { + $r = $s->foo("hello"); + print "res $r\n"; die("Spam::foo(char *)"); } @@ -275,6 +278,8 @@ if (!(overload_simple::fid(3.0, "3") eq "fid:doubleint")) { } if (!(overload_simple::fid("3.0", "3.0") eq "fid:doubledouble")) { + $r = overload_simple::fid("3.0", "3.0"); + print "$r \n"; die("fid(double,double)"); } diff --git a/SWIG/Examples/test-suite/python/Makefile.in b/SWIG/Examples/test-suite/python/Makefile.in index 5657a7205..283db3980 100644 --- a/SWIG/Examples/test-suite/python/Makefile.in +++ b/SWIG/Examples/test-suite/python/Makefile.in @@ -35,6 +35,7 @@ CPP_TEST_CASES += \ li_std_wstream \ li_std_wstring \ nondynamic \ + overload_simple_cast \ primitive_types \ std_containers \ swigobject \ @@ -100,3 +101,4 @@ cvsignore: @echo imports_b.py @echo template_typedef_import.py + diff --git a/SWIG/Examples/test-suite/python/overload_simple_cast.i b/SWIG/Examples/test-suite/python/overload_simple_cast.i new file mode 100644 index 000000000..d274722c0 --- /dev/null +++ b/SWIG/Examples/test-suite/python/overload_simple_cast.i @@ -0,0 +1,4 @@ +// Simple tests of overloaded functions +%module("castmode") overload_simple_cast + +%include overload_simple.i diff --git a/SWIG/Examples/test-suite/python/overload_simple_cast_runme.py b/SWIG/Examples/test-suite/python/overload_simple_cast_runme.py new file mode 100644 index 000000000..be2ceca16 --- /dev/null +++ b/SWIG/Examples/test-suite/python/overload_simple_cast_runme.py @@ -0,0 +1,165 @@ +from overload_simple_cast import * + +class Ai: + def __init__(self,x): + self.x = x + + def __int__(self): + return self.x + +class Ad: + def __init__(self,x): + self.x = x + + def __float__(self): + return self.x + +ai = Ai(4) + +ad = Ad(5.0) +add = Ad(5.5) + +try: + fint(add) + good = 0 +except: + good = 1 + +if not good: + raise RuntimeError, "fint(int)" + + +if fint(ad) != "fint:int": + raise RuntimeError, "fint(int)" + +if fdouble(ad) != "fdouble:double": + raise RuntimeError, "fdouble(double)" + +if fint(ai) != "fint:int": + raise RuntimeError, "fint(int)" + +if fint(5.0) != "fint:int": + raise RuntimeError, "fint(int)" + +if fint(3) != "fint:int": + raise RuntimeError, "fint(int)" +if fint(3.0) != "fint:int": + raise RuntimeError, "fint(int)" + +if fdouble(ad) != "fdouble:double": + raise RuntimeError, "fdouble(double)" +if fdouble(3) != "fdouble:double": + raise RuntimeError, "fdouble(double)" +if fdouble(3.0) != "fdouble:double": + raise RuntimeError, "fdouble(double)" + +if fid(3,3.0) != "fid:intdouble": + raise RuntimeError, "fid:intdouble" + +if fid(3.0,3) != "fid:doubleint": + raise RuntimeError, "fid:doubleint" + +if fid(ad,ai) != "fid:doubleint": + raise RuntimeError, "fid:doubleint" + +if fid(ai,ad) != "fid:intdouble": + raise RuntimeError, "fid:intdouble" + + + +if foo(3) != "foo:int": + raise RuntimeError, "foo(int)" + +if foo(3.0) != "foo:double": + raise RuntimeError, "foo(double)" + +if foo("hello") != "foo:char *": + raise RuntimeError, "foo(char *)" + +f = Foo() +b = Bar() + +if foo(f) != "foo:Foo *": + raise RuntimeError, "foo(Foo *)" + +if foo(b) != "foo:Bar *": + raise RuntimeError, "foo(Bar *)" + +v = malloc_void(32) + +if foo(v) != "foo:void *": + raise RuntimeError, "foo(void *)" + +s = Spam() + +if s.foo(3) != "foo:int": + raise RuntimeError, "Spam::foo(int)" + +if s.foo(3.0) != "foo:double": + raise RuntimeError, "Spam::foo(double)" + +if s.foo("hello") != "foo:char *": + raise RuntimeError, "Spam::foo(char *)" + +if s.foo(f) != "foo:Foo *": + raise RuntimeError, "Spam::foo(Foo *)" + +if s.foo(b) != "foo:Bar *": + raise RuntimeError, "Spam::foo(Bar *)" + +if s.foo(v) != "foo:void *": + raise RuntimeError, "Spam::foo(void *)" + +if Spam_bar(3) != "bar:int": + raise RuntimeError, "Spam::bar(int)" + +if Spam_bar(3.0) != "bar:double": + raise RuntimeError, "Spam::bar(double)" + +if Spam_bar("hello") != "bar:char *": + raise RuntimeError, "Spam::bar(char *)" + +if Spam_bar(f) != "bar:Foo *": + raise RuntimeError, "Spam::bar(Foo *)" + +if Spam_bar(b) != "bar:Bar *": + raise RuntimeError, "Spam::bar(Bar *)" + +if Spam_bar(v) != "bar:void *": + raise RuntimeError, "Spam::bar(void *)" + +# Test constructors + +s = Spam() +if s.type != "none": + raise RuntimeError, "Spam()" + +s = Spam(3) +if s.type != "int": + raise RuntimeError, "Spam(int)" + +s = Spam(3.4) +if s.type != "double": + raise RuntimeError, "Spam(double)" + +s = Spam("hello") +if s.type != "char *": + raise RuntimeError, "Spam(char *)" + +s = Spam(f) +if s.type != "Foo *": + raise RuntimeError, "Spam(Foo *)" + +s = Spam(b) +if s.type != "Bar *": + raise RuntimeError, "Spam(Bar *)" + +s = Spam(v) +if s.type != "void *": + raise RuntimeError, "Spam(void *)" + + + + + +free_void(v) diff --git a/SWIG/Lib/perl5/perlprimtypes.swg b/SWIG/Lib/perl5/perlprimtypes.swg index 371842c4a..b59c53add 100644 --- a/SWIG/Lib/perl5/perlprimtypes.swg +++ b/SWIG/Lib/perl5/perlprimtypes.swg @@ -15,7 +15,7 @@ SWIG_From_dec(long)(long value) } %fragment(SWIG_AsVal_frag(long),"header", - fragment=SWIG_AsVal_frag(double)) { + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(long)(SV *obj, long* val) { @@ -34,25 +34,16 @@ SWIG_AsVal_dec(long)(SV *obj, long* val) } else { if (*endptr == '\0') { if (val) *val = v; - return SWIG_AddCast(SWIG_OK); + return SWIG_CastRank(SWIG_OK); } } } if (!dispatch) { double d; - int res = SWIG_AsVal(double)(obj,&d); - if (SWIG_IsOK(res)) { - if (LONG_MIN <= d && d <= LONG_MAX) { - double rd = rint(d); - if (errno) { - errno = 0; - } else { - if (rd == d) { - if (val) *val = (long)(rd); - return SWIG_AddCast(res); - } - } - } + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; } } } @@ -74,7 +65,7 @@ SWIG_From_dec(unsigned long)(unsigned long value) } %fragment(SWIG_AsVal_frag(unsigned long),"header", - fragment=SWIG_AsVal_frag(double)) { + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val) { @@ -101,29 +92,19 @@ SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val) } else { if (*endptr == '\0') { if (val) *val = v; - return SWIG_AddCast(SWIG_OK); + return SWIG_CastRank(SWIG_OK); } } } if (!dispatch) { double d; - int res = SWIG_AsVal(double)(obj,&d); - if (SWIG_IsOK(res) && (d >= 0)) { - if (d <= ULONG_MAX) { - double rd = rint(d); - if (errno) { - errno = 0; - } else { - if (rd == d) { - if (val) *val = (long)(rd); - return SWIG_AddCast(res); - } - } - } + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; } } } - return SWIG_TypeError; } } @@ -149,8 +130,8 @@ SWIG_From_dec(long long)(long long value) } %fragment(SWIG_AsVal_frag(long long),"header", - fragment=SWIG_AsVal_frag(double), - fragment="") { + fragment="", + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(long long)(SV *obj, long long *val) @@ -170,25 +151,16 @@ SWIG_AsVal_dec(long long)(SV *obj, long long *val) } else { if (*endptr == '\0') { if (val) *val = v; - return SWIG_AddCast(SWIG_OK); + return SWIG_CastRank(SWIG_OK); } } } if (!dispatch) { double d; - int res = SWIG_AsVal(double)(obj,&d); - if (SWIG_IsOK(res)) { - if (LLONG_MIN <= d && d <= LLONG_MAX) { - double rd = rint(d); - if (errno) { - errno = 0; - } else { - if (rd == d) { - if (val) *val = (long long)(rd); - return SWIG_AddCast(res); - } - } - } + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LLONG_MIN, LLONG_MAX)) { + if (val) *val = (long long)(d); + return res; } } } @@ -217,8 +189,8 @@ SWIG_From_dec(unsigned long long)(unsigned long long value) } %fragment(SWIG_AsVal_frag(unsigned long long),"header", - fragment=SWIG_AsVal_frag(double), - fragment="") { + fragment="", + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(unsigned long long)(SV *obj, unsigned long long *val) { @@ -237,25 +209,16 @@ SWIG_AsVal_dec(unsigned long long)(SV *obj, unsigned long long *val) } else { if (*endptr == '\0') { if (val) *val = v; - return SWIG_AddCast(SWIG_OK); + return SWIG_CastRank(SWIG_OK); } } } if (!dispatch) { double d; - int res = SWIG_AsVal(double)(obj,&d); - if (SWIG_IsOK(res) && (d >=0 )) { - if (d <= ULLONG_MAX) { - double rd = rint(d); - if (errno) { - errno = 0; - } else { - if (rd == d) { - if (val) *val = (unsigned long long)(rd); - return SWIG_AddCast(res); - } - } - } + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULLONG_MAX)) { + if (val) *val = (unsigned long long)(d); + return res; } } } @@ -283,8 +246,8 @@ SWIG_AsVal_dec(double)(SV *obj, double *val) if (val) *val = SvNV(obj); return SWIG_OK; } else if (SvIOK(obj)) { - if (val) *val = SvIV(obj); - return SWIG_AddCast(SWIG_OK); + if (val) *val = (double) SvIV(obj); + return SWIG_CastRank(SWIG_OK); } else { const char *nptr = SvPV(obj, PL_na); if (nptr) { @@ -296,7 +259,7 @@ SWIG_AsVal_dec(double)(SV *obj, double *val) } else { if (*endptr == '\0') { if (val) *val = v; - return SWIG_AddCast(SWIG_OK); + return SWIG_CastRank(SWIG_OK); } } } diff --git a/SWIG/Lib/python/pycomplex.swg b/SWIG/Lib/python/pycomplex.swg index 6402610fc..8a4bcaf27 100644 --- a/SWIG/Lib/python/pycomplex.swg +++ b/SWIG/Lib/python/pycomplex.swg @@ -32,11 +32,12 @@ SWIG_AsVal(Type) (PyObject *o, Type* val) return SWIG_OK; } else { double d; - if (SWIG_AsVal(double)(o, &d) == SWIG_OK) { + int res = SWIG_CastRank(SWIG_AsVal(double)(o, &d)); + if (SWIG_IsOK(res)) { if (val) *val = Constructor(d, 0.0); - return SWIG_OK; + return res; } - } + } return SWIG_TypeError; } } @@ -61,10 +62,11 @@ SWIG_AsVal(Type)(PyObject *o, Type *val) return SWIG_OverflowError; } } else { - float re; - if (SWIG_AsVal(float)(o, &re) == SWIG_OK) { + float re; + int res = SWIG_CastRank(SWIG_AsVal(float)(o, &re)); + if (SWIG_IsOK(res)) { if (val) *val = Constructor(re, 0.0); - return SWIG_OK; + return res; } } return SWIG_TypeError; diff --git a/SWIG/Lib/python/pyprimtypes.swg b/SWIG/Lib/python/pyprimtypes.swg index 7aaba1757..41072faf7 100644 --- a/SWIG/Lib/python/pyprimtypes.swg +++ b/SWIG/Lib/python/pyprimtypes.swg @@ -27,8 +27,8 @@ SWIG_AsVal_dec(bool)(PyObject *obj, bool *val) return SWIG_OK; } else { long v = 0; - int res = SWIG_AsVal(long)(obj, val ? &v : 0); - if (res == SWIG_OK && val) *val = v ? true : false; + int res = SWIG_CastRank(SWIG_AsVal(long)(obj, val ? &v : 0)); + if (SWIG_IsOK(res) && val) *val = v ? true : false; return res; } } @@ -41,7 +41,8 @@ SWIG_AsVal_dec(bool)(PyObject *obj, bool *val) %define_as(SWIG_From_dec(long), PyInt_FromLong) } -%fragment(SWIG_AsVal_frag(long),"header") { +%fragment(SWIG_AsVal_frag(long),"header", + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(long)(PyObject *obj, long* val) { @@ -57,6 +58,26 @@ SWIG_AsVal_dec(long)(PyObject *obj, long* val) PyErr_Clear(); } } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_CastRank(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } +%#endif return SWIG_TypeError; } } @@ -73,7 +94,8 @@ SWIG_From_dec(unsigned long)(unsigned long value) } } -%fragment(SWIG_AsVal_frag(unsigned long),"header") { +%fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="SWIG_CanCastAsInteger") { SWIGINTERN int SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val) { @@ -94,6 +116,30 @@ SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val) PyErr_Clear(); } } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (v >= 0) { + if (val) *val = v; + return SWIG_CastRank(SWIG_OK); + } else { + return SWIG_OverflowError; + } + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +%#endif return SWIG_TypeError; } } @@ -111,7 +157,9 @@ SWIG_From_dec(long long)(long long value) } } -%fragment(SWIG_AsVal_frag(long long),"header") { +%fragment(SWIG_AsVal_frag(long long),"header", + fragment="SWIG_CanCastAsInteger", + fragment="") { SWIGINTERN int SWIG_AsVal_dec(long long)(PyObject *obj, long long *val) { @@ -127,6 +175,26 @@ SWIG_AsVal_dec(long long)(PyObject *obj, long long *val) PyErr_Clear(); } } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_CastRank(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LLONG_MIN, LLONG_MAX)) { + if (val) *val = (long long)(d); + return res; + } + } + } +%#endif return SWIG_TypeError; } } @@ -145,7 +213,9 @@ SWIG_From_dec(unsigned long long)(unsigned long long value) } %fragment(SWIG_AsVal_frag(unsigned long long),"header", - fragment=SWIG_AsVal_frag(unsigned long)) { + fragment=SWIG_AsVal_frag(unsigned long), + fragment="SWIG_CanCastAsInteger", + fragment="") { SWIGINTERN int SWIG_AsVal_dec(unsigned long long)(PyObject *obj, unsigned long long *val) { @@ -160,9 +230,33 @@ SWIG_AsVal_dec(unsigned long long)(PyObject *obj, unsigned long long *val) } else { unsigned long v; int res = SWIG_AsVal(unsigned long)(obj,&v); - if (res == SWIG_OK && val) *val = v; + if (SWIG_IsOK(res) && val) *val = v; return res; } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (v >= 0) { + if (val) *val = v; + return SWIG_CastRank(SWIG_OK); + } else { + return SWIG_OverflowError; + } + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_CastRank(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULLONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +%#endif return SWIG_TypeError; } } @@ -192,6 +286,27 @@ SWIG_AsVal_dec(double)(PyObject *obj, double *val) PyErr_Clear(); } } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + double d = PyFloat_AsDouble(obj); + if (!PyErr_Occurred()) { + if (val) *val = d; + return SWIG_CastRank(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + long v = PyInt_AsLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_CastRank(SWIG_CastRank(SWIG_OK)); + } else { + PyErr_Clear(); + } + } + } +%#endif return SWIG_TypeError; } } diff --git a/SWIG/Lib/python/pystdcommon.swg b/SWIG/Lib/python/pystdcommon.swg index 1b0d7191b..80f1689cd 100644 --- a/SWIG/Lib/python/pystdcommon.swg +++ b/SWIG/Lib/python/pystdcommon.swg @@ -99,7 +99,7 @@ namespace swig { struct traits_as { static Type as(PyObject *obj, bool throw_error) { Type v; - if (!obj || (asval(obj, &v) != SWIG_OK)) { + if (!obj || !SWIG_IsOK(asval(obj, &v))) { if (!PyErr_Occurred()) { %type_error(swig::type_name()); } @@ -160,7 +160,7 @@ namespace swig { template struct traits_check { static bool check(PyObject *obj) { - return obj && (asval(obj, (Type *)(0)) == SWIG_OK); + return obj && SWIG_IsOK(asval(obj, (Type *)(0))); } }; diff --git a/SWIG/Lib/swigerrors.swg b/SWIG/Lib/swigerrors.swg index 0e37686cb..5b44a2229 100644 --- a/SWIG/Lib/swigerrors.swg +++ b/SWIG/Lib/swigerrors.swg @@ -12,3 +12,4 @@ #define SWIG_AttributeError -11 #define SWIG_MemoryError -12 + diff --git a/SWIG/Lib/swigrun.swg b/SWIG/Lib/swigrun.swg index af2999a73..19b07e53d 100644 --- a/SWIG/Lib/swigrun.swg +++ b/SWIG/Lib/swigrun.swg @@ -58,10 +58,17 @@ #define SWIG_ERROR -1 /* Flags to manage cast and return states */ -#define SWIG_MAX_CAST_RANK 4 +#ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +#endif +#ifndef SWIG_MAX_CAST_RANK +# define SWIG_MAX_CAST_RANK 2 /* Two cast allowed */ +#endif #define SWIG_IsOK(r) (r >= 0) -#define SWIG_AddCast(r) (SWIG_IsOK(r) ? (r + 1) : r) -#define SWIG_GetCastRank(r) (SWIG_IsOK(r) ? ((r < SWIG_MAX_CAST_RANK) ? (r + 1) : 0) : 0) +SWIGINTERNINLINE int +SWIG_CastRank(int r) { + return (SWIG_IsOK(r)) ? ((r < SWIG_MAX_CAST_RANK) ? (r + 1) : SWIG_ERROR) : r; +} #include diff --git a/SWIG/Lib/typemaps/inoutlist.swg b/SWIG/Lib/typemaps/inoutlist.swg index cbb937e25..3da1c0366 100644 --- a/SWIG/Lib/typemaps/inoutlist.swg +++ b/SWIG/Lib/typemaps/inoutlist.swg @@ -103,9 +103,9 @@ or you can use the %apply directive : } %typemap(typecheck,noblock=1,precedence=code,fragment=asval_frag) Type *INPUT, Type &INPUT { void *ptr; - int res = asval_meth($input, 0); + int res = SWIG_CastRank(asval_meth($input, 0)); if (SWIG_IsOK(res)) { - $1 = SWIG_GetCastRank(res); + $1 = res; } else { $1 = %check_input_ptr($input,&ptr,$1_descriptor,0); } diff --git a/SWIG/Lib/typemaps/primtypes.swg b/SWIG/Lib/typemaps/primtypes.swg index c245f4b4a..339463104 100644 --- a/SWIG/Lib/typemaps/primtypes.swg +++ b/SWIG/Lib/typemaps/primtypes.swg @@ -197,6 +197,40 @@ SWIG_AsVal_dec(ptrdiff_t)(SWIG_Object obj, ptrdiff_t *val) } } +%fragment("SWIG_CanCastAsInteger","header", + fragment=SWIG_AsVal_frag(double), + fragment="", + fragment="") { +SWIGINTERNINLINE int +SWIG_CanCastAsInteger(double *d, double min, double max) { + double x = *d; + if (min <= x && x <= max) { +%#ifndef SWIG_HAS_NO_RINT + /* Use the python mechanism to round, or so */ + double rd = (x < 0) ? ceil(x) : floor(x); +%#else + double rd = rint(x); +%#endif + if ((errno == EDOM) || (errno == ERANGE)) { + errno = 0; + } else { + if (rd == x) { + return 1; + } else { + double diff = rd - x; + double summ = rd + x; + double reps = diff/summ; + if (fabs(reps) < 8*DBL_EPSILON) { + *d = rd; + return 1; + } + } + } + } + return 0; +} +} + /* ------------------------------------------------------------ * Generate the typemaps for primitive type * ------------------------------------------------------------ */ diff --git a/SWIG/Lib/typemaps/valtypes.swg b/SWIG/Lib/typemaps/valtypes.swg index c5b286791..7a686a34d 100644 --- a/SWIG/Lib/typemaps/valtypes.swg +++ b/SWIG/Lib/typemaps/valtypes.swg @@ -161,8 +161,8 @@ %define %value_typecheck_typemap(check,asval_meth,frag,Type...) %typemap(typecheck,noblock=1,precedence=check,fragment=frag) Type, const Type& { - int res = asval_meth($input, NULL); - $1 = SWIG_GetCastRank(res); + int res = SWIG_CastRank(asval_meth($input, NULL)); + $1 = SWIG_IsOK(res) ? res : 0; } %enddef diff --git a/SWIG/Source/Modules/overload.cxx b/SWIG/Source/Modules/overload.cxx index 86fc7cba3..7879c5608 100644 --- a/SWIG/Source/Modules/overload.cxx +++ b/SWIG/Source/Modules/overload.cxx @@ -372,7 +372,7 @@ Swig_overload_dispatch_cast(Node *n, const String_or_char *fmt, int *maxargs) { String *sw = NewString(""); Printf(f,"{\n"); Printf(f,"unsigned long _index = 0;\n"); - Printf(f,"double _rank = 0; \n"); + Printf(f,"SWIG_TypeRank _rank = 0; \n"); /* Get a list of methods ranked by precedence values and argument count */ List *dispatch = Swig_overload_rank(n, true); @@ -401,8 +401,8 @@ Swig_overload_dispatch_cast(Node *n, const String_or_char *fmt, int *maxargs) { } else { Printf(f,"if (%s >= %d) {\n", argc_template_string, num_required); } - Printf(f,"double _ranki = 0;\n"); - Printf(f,"double _pi = 1;\n",num_arguments); + Printf(f,"SWIG_TypeRank _ranki = 0;\n"); + Printf(f,"SWIG_TypeRank _pi = 1;\n",num_arguments); /* create a list with the wrappers that collide with the current one based on argument number */ @@ -471,7 +471,7 @@ Swig_overload_dispatch_cast(Node *n, const String_or_char *fmt, int *maxargs) { if (emitcheck) { if (need_v) { - Printf(f,"int _v;\n"); + Printf(f,"int _v = 0;\n"); need_v = 0; } if (j >= num_required) { @@ -631,7 +631,7 @@ Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) { if (emitcheck) { if (need_v) { - Printf(f,"int _v = 1;\n"); + Printf(f,"int _v = 0;\n"); need_v = 0; } if (j >= num_required) { diff --git a/SWIG/Source/Modules/python.cxx b/SWIG/Source/Modules/python.cxx index 5463c081f..837a5460c 100644 --- a/SWIG/Source/Modules/python.cxx +++ b/SWIG/Source/Modules/python.cxx @@ -69,6 +69,7 @@ static int proxydel = 1; static int fastunpack = 0; static int modernargs = 0; static int aliasobj0 = 0; +static int castmode = 0; /* flags for the make_autodoc function */ enum autodoc_t { @@ -114,6 +115,8 @@ Python Options (available with -python)\n\ -nofastunpack - Use traditional UnpackTuple method to parse the argument functions (default) \n\ -aliasobj0 - Alias obj0 when using fastunpack, needed for some old typemaps \n\ -noaliasobj0 - Don't generate an obj0 alias when using fastunpack (default) \n\ + -castmode - Enable the casting mode, which allows implicit cast between types\n\ + -nocastmode - Disable the casting mode (default)\n\ -O - Enable all the optimizations options: \n\ -modern -fastdispatch -dirvtable -nosafecstrings -fvirtual -noproxydel -fastunpack -modernargs\n\ \n"; @@ -294,6 +297,12 @@ public: } else if (strcmp(argv[i],"-nofastunpack") == 0) { fastunpack = 0; Swig_mark_arg(i); + } else if (strcmp(argv[i],"-castmode") == 0) { + castmode = 1; + Swig_mark_arg(i); + } else if (strcmp(argv[i],"-nocastmode") == 0) { + castmode = 0; + Swig_mark_arg(i); } else if (strcmp(argv[i],"-modernargs") == 0) { modernargs = 1; Swig_mark_arg(i); @@ -394,6 +403,12 @@ public: if (Getattr(options, "threads")) { threads = 1; } + if (Getattr(options, "castmode")) { + castmode = 1; + } + if (Getattr(options, "nocastmode")) { + castmode = 0; + } mod_docstring = Getattr(options, "docstring"); package = Getattr(options, "package"); } @@ -464,6 +479,10 @@ public: Printf(f_runtime,"#define SWIG_PYTHON_DIRECTOR_NO_VTABLE\n"); } + if (castmode) { + Printf(f_runtime,"#define SWIG_PYTHON_CAST_MODE\n"); + } + /* Set module name */ module = Copy(Getattr(n,"name")); @@ -1301,11 +1320,14 @@ public: int allow_thread = threads_enable(n); String *tmp = NewString(""); - - String *dispatch = funpack ? - Swig_overload_dispatch(n,"return %s(self, argv);",&maxargs) - : Swig_overload_dispatch(n,"return %s(self, args);",&maxargs); - + String *dispatch; + const char *dispatch_code = funpack ? "return %s(self, argv);" : "return %s(self, args);"; + + if (castmode) { + dispatch = Swig_overload_dispatch_cast(n,dispatch_code,&maxargs); + } else { + dispatch = Swig_overload_dispatch(n,dispatch_code,&maxargs); + } /* Generate a dispatch wrapper for all overloaded functions */