diff --git a/CHANGES.current b/CHANGES.current index b97d7709d..a05694695 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2021-03-23: wsfulton + #1942 [Python] Fix compilation error in wrappers when using -builtin + and wrapping varargs in constructors. + 2021-03-22: goto40 #1977 Fix handling of template template parameters. diff --git a/Examples/test-suite/kwargs_feature.i b/Examples/test-suite/kwargs_feature.i index 2b662caeb..dd5b2638d 100644 --- a/Examples/test-suite/kwargs_feature.i +++ b/Examples/test-suite/kwargs_feature.i @@ -126,3 +126,21 @@ struct Extending2 {}; struct ExtendingOptArgs1 {}; struct ExtendingOptArgs2 {}; %} + +// Varargs +%warnfilter(SWIGWARN_LANG_VARARGS_KEYWORD) VarargConstructor::VarargConstructor; // Can't wrap varargs with keyword arguments enabled +%warnfilter(SWIGWARN_LANG_VARARGS_KEYWORD) VarargConstructor::vararg_method; // Can't wrap varargs with keyword arguments enabled +%inline %{ +struct VarargConstructor { + char *str; + VarargConstructor(const char *fmt, ...) { + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } + void vararg_method(const char *fmt, ...) { + delete [] str; + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } +}; +%} diff --git a/Examples/test-suite/python/kwargs_feature_runme.py b/Examples/test-suite/python/kwargs_feature_runme.py index 31d49d221..387658ec3 100644 --- a/Examples/test-suite/python/kwargs_feature_runme.py +++ b/Examples/test-suite/python/kwargs_feature_runme.py @@ -122,3 +122,18 @@ try: raise RuntimeError("missed exception") except TypeError as e: pass + +# Varargs +f = VarargConstructor(fmt="Ciao") +f.vararg_method(fmt="Bonjour") +try: + f = VarargConstructor(nonexistent="Ciao") + raise RuntimeError("missed exception") +except TypeError as e: + pass + +try: + f.vararg_method(nonexistent="Bonjour") + raise RuntimeError("missed exception") +except TypeError as e: + pass diff --git a/Examples/test-suite/python/varargs_runme.py b/Examples/test-suite/python/varargs_runme.py index 8f90d5cde..13f85a75f 100644 --- a/Examples/test-suite/python/varargs_runme.py +++ b/Examples/test-suite/python/varargs_runme.py @@ -3,6 +3,10 @@ import varargs if varargs.test("Hello") != "Hello": raise RuntimeError("Failed") +vc = varargs.VarargConstructor("Hey there") +if vc.str != "Hey there": + raise RuntimeError("Failed") + f = varargs.Foo("Greetings") if f.str != "Greetings": raise RuntimeError("Failed") diff --git a/Examples/test-suite/varargs.i b/Examples/test-suite/varargs.i index dd56cb073..68c7a1714 100644 --- a/Examples/test-suite/varargs.i +++ b/Examples/test-suite/varargs.i @@ -1,17 +1,31 @@ -// Tests SWIG's *default* handling of varargs (function varargs, not preprocessor varargs). +// Tests SWIG's handling of varargs (function varargs, not preprocessor varargs). // The default behavior is to simply ignore the varargs. %module varargs +// Default handling of varargs + +%inline %{ +char *test(const char *fmt, ...) { + return (char *) fmt; +} + +struct VarargConstructor { + char *str; + VarargConstructor(const char *fmt, ...) { + str = new char[strlen(fmt) + 1]; + strcpy(str, fmt); + } +}; +%} + +// %varargs support + %varargs(int mode = 0) test_def; %varargs(int mode = 0) Foo::Foo; %varargs(int mode = 0) Foo::statictest(const char*fmt, ...); %varargs(2, int mode = 0) test_plenty(const char*fmt, ...); %inline %{ -char *test(const char *fmt, ...) { - return (char *) fmt; -} - const char *test_def(const char *fmt, ...) { return fmt; } @@ -40,5 +54,4 @@ public: const char *test_plenty(const char *fmt, ...) { return fmt; } - %} diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index c9bc21742..4ef0eb929 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -2753,7 +2753,7 @@ public: if (!varargs) { Printv(f->def, linkage, wrap_return, wname, "(PyObject *", self_param, ", PyObject *args", builtin_kwargs, ") {", NIL); } else { - Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs) {", NIL); + Printv(f->def, linkage, wrap_return, wname, "__varargs__", "(PyObject *", self_param, ", PyObject *args, PyObject *varargs", builtin_kwargs, ") {", NIL); } if (allow_kwargs) { Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number, "Can't use keyword arguments with overloaded functions (%s).\n", Swig_name_decl(n)); @@ -3253,10 +3253,10 @@ public: Printf(f->code, " Py_XINCREF(swig_obj[i + %d]);\n", num_fixed_arguments); Printf(f->code, "}\n"); } else { - Printf(f->code, "newargs = PyTuple_GetSlice(args,0,%d);\n", num_fixed_arguments); - Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args));\n", num_fixed_arguments); + Printf(f->code, "newargs = PyTuple_GetSlice(args, 0, %d);\n", num_fixed_arguments); + Printf(f->code, "varargs = PyTuple_GetSlice(args, %d, PyTuple_Size(args));\n", num_fixed_arguments); } - Printf(f->code, "resultobj = %s__varargs__(%s,newargs,varargs);\n", wname, builtin ? "self" : "NULL"); + Printf(f->code, "resultobj = %s__varargs__(%s, newargs, varargs%s);\n", wname, builtin ? "self" : "NULL", strlen(builtin_kwargs) == 0 ? "" : ", kwargs"); Append(f->code, "Py_XDECREF(newargs);\n"); Append(f->code, "Py_XDECREF(varargs);\n"); Append(f->code, "return resultobj;\n");