From 5569d91bd02432eef4fb7ef2c2ed0df2f51c8472 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 22 Apr 2015 20:37:55 +0200 Subject: [PATCH] Fix handling of "default" typemap in Python. Use "compact" arguments form for the function if "default" typemap is defined for any of its arguments to allow omitting this argument when calling it from Python. Closes #377. --- CHANGES.current | 3 +++ Examples/test-suite/default_args.i | 4 ++++ .../test-suite/python/default_args_runme.py | 6 ++++++ Source/Modules/python.cxx | 21 ++++++++++++------- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/CHANGES.current b/CHANGES.current index 94eac2347..24c36d6a0 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.6 (in progress) =========================== +2015-04-23: vadz + [Python] Make "default" typemap work again (#330, #377). + 2015-04-23: vadz [Python] Fix the use of default values for the pointer types (#365, #376). diff --git a/Examples/test-suite/default_args.i b/Examples/test-suite/default_args.i index 2c1187fb5..4ab24d335 100644 --- a/Examples/test-suite/default_args.i +++ b/Examples/test-suite/default_args.i @@ -114,6 +114,8 @@ %rename(renamed2arg) Foo::renameme(int x) const; %rename(renamed1arg) Foo::renameme() const; +%typemap(default) double* null_by_default "$1=0;"; + %inline %{ typedef void* MyHandle; @@ -144,6 +146,8 @@ // test default values for pointer arguments int double_if_void_ptr_is_null(int n, void* p = NULL) { return p ? n : 2*n; } int double_if_handle_is_null(int n, MyHandle h = 0) { return h ? n : 2*n; } + int double_if_dbl_ptr_is_null(int n, double* null_by_default) + { return null_by_default ? n : 2*n; } }; int Foo::bar = 1; int Foo::spam = 2; diff --git a/Examples/test-suite/python/default_args_runme.py b/Examples/test-suite/python/default_args_runme.py index 62ba0ea78..18cc2c27a 100644 --- a/Examples/test-suite/python/default_args_runme.py +++ b/Examples/test-suite/python/default_args_runme.py @@ -43,6 +43,12 @@ def run(module_name): if f.double_if_handle_is_null(5) != 10: raise RuntimeError + if f.double_if_dbl_ptr_is_null(6, None) != 12: + raise RuntimeError + + if f.double_if_dbl_ptr_is_null(7) != 14: + raise RuntimeError + try: f = default_args.Foo(1) error = 1 diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 5ae4b6d55..ca9e7f2ba 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1999,9 +1999,9 @@ public: * at C++ code level where they can always be handled. * ------------------------------------------------------------ */ bool is_representable_as_pyargs(Node *n) { - bool is_representable = true; - ParmList *plist = CopyParmList(Getattr(n, "parms")); + Swig_typemap_attach_parms("default", plist, NULL); + Parm *p; Parm *pnext; @@ -2017,16 +2017,23 @@ public: if (!pnext) { pnext = nextSibling(p); } + + // "default" typemap can contain arbitrary C++ code, so while it could, in + // principle, be possible to examine it and check if it's just something + // simple of the form "$1 = expression" and then use convertValue() to + // check if expression can be used in Python, but for now we just + // pessimistically give up and prefer to handle this at C++ level only. + if (Getattr(p, "tmap:default")) + return false; + if (String *value = Getattr(p, "value")) { String *type = Getattr(p, "type"); - if (!convertValue(value, type)) { - is_representable = false; - break; - } + if (!convertValue(value, type)) + return false; } } - return is_representable; + return true; }