diff --git a/CHANGES.current b/CHANGES.current index 6e785379d..8b087c75b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,6 +4,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.4 (in progress) =========================== +2011-04-12: szager + Fixed bug 1163440: vararg typemaps. + 2011-04-12: szager Fixed bug #3285386: parse error from 'operator T*&()'. Added operator_pointer_ref test case to demonstrate. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 892ced2c1..9f15df50f 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -510,7 +510,8 @@ C_TEST_CASES += \ typedef_struct \ typemap_subst \ union_parameter \ - unions + unions \ + varargs_typemap # Multi-module C++ test cases . (Can be run individually using make testcase.multicpptest) diff --git a/Examples/test-suite/python/varargs_typemap_runme.py b/Examples/test-suite/python/varargs_typemap_runme.py new file mode 100644 index 000000000..8622051da --- /dev/null +++ b/Examples/test-suite/python/varargs_typemap_runme.py @@ -0,0 +1,4 @@ +import varargs_typemap + +if (varargs_typemap.testfunc(1, 2.0, "three") != "three") : + raise RuntimeError("testfunc failed!") diff --git a/Examples/test-suite/varargs_typemap.i b/Examples/test-suite/varargs_typemap.i new file mode 100644 index 000000000..54c0526f8 --- /dev/null +++ b/Examples/test-suite/varargs_typemap.i @@ -0,0 +1,43 @@ +%module varargs_typemap + + /* The typemap and action are taken from the "Variable length arguments" + * chapter of the SWIG manual. + */ + +%typemap(in) (...)(char *args[10]) { + int i; + int argc; + for (i = 0; i < 10; i++) args[i] = 0; + argc = PyTuple_Size(varargs); + if (argc > 10) { + PyErr_SetString(PyExc_ValueError,"Too many arguments"); + return NULL; + } + for (i = 0; i < argc; i++) { + PyObject *o = PyTuple_GetItem(varargs,i); + if (!PyString_Check(o)) { + PyErr_SetString(PyExc_ValueError,"Expected a string"); + return NULL; + } + args[i] = PyString_AsString(o); + } + $1 = (void *) args; +} + +%feature("action") testfunc { + char **args = (char **) arg3; + result = testfunc(arg1, arg2, args[0], args[1], args[2], args[3], args[4], + args[5],args[6],args[7],args[8],args[9], NULL); +} + +%inline { +char* testfunc (int arg1, double arg2, ...) +{ + va_list ap; + char *c; + va_start(ap, arg2); + c = va_arg(ap, char*); + va_end(ap); + return c; +} +} diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index dde0b07d1..ff88fda8f 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -1999,6 +1999,7 @@ public: int num_required; int num_arguments; + int num_fixed_arguments; int tuple_required; int tuple_arguments; int varargs = 0; @@ -2066,7 +2067,7 @@ public: emit_attach_parmmaps(l, f); Setattr(n, "wrap:parms", l); /* Get number of required and total arguments */ - tuple_arguments = num_arguments = emit_num_arguments(l); + tuple_arguments = num_fixed_arguments = num_arguments = emit_num_arguments(l); tuple_required = num_required = emit_num_required(l); if (add_self) { --tuple_arguments; @@ -2171,7 +2172,6 @@ public: int use_parse = 0; Append(kwargs, "{"); for (i = 0, p = l; i < num_arguments; i++) { - bool parse_from_tuple = (i > 0 || !add_self); while (checkAttribute(p, "tmap:in:numinputs", "0")) { p = Getattr(p, "tmap:in:next"); } @@ -2179,6 +2179,11 @@ public: SwigType *pt = Getattr(p, "type"); String *pn = Getattr(p, "name"); String *ln = Getattr(p, "lname"); + bool parse_from_tuple = (i > 0 || !add_self); + if (SwigType_type(pt) == T_VARARGS) { + parse_from_tuple = false; + num_fixed_arguments -= atoi(Char(Getattr(p, "tmap:in:numinputs"))); + } if (!parse_from_tuple) sprintf(source, "self"); else if (funpack) @@ -2600,19 +2605,19 @@ public: Wrapper_add_local(f, "newargs", "PyObject *newargs"); if (funpack) { Wrapper_add_local(f, "i", "int i"); - Printf(f->code, "newargs = PyTuple_New(%d);\n", num_arguments); - Printf(f->code, "for (i = 0; i < %d; ++i) {\n", num_arguments); + Printf(f->code, "newargs = PyTuple_New(%d);\n", num_fixed_arguments); + Printf(f->code, "for (i = 0; i < %d; ++i) {\n", num_fixed_arguments); Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i]);\n"); Printf(f->code, " Py_XINCREF(swig_obj[i]);\n"); Printf(f->code, "}\n"); - Printf(f->code, "varargs = PyTuple_New(nobjs > %d ? nobjs - %d : 0);\n", num_arguments, num_arguments); - Printf(f->code, "for (i = 0; i < nobjs - %d; ++i) {\n", num_arguments); - Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i + %d]);\n", num_arguments); - Printf(f->code, " Py_XINCREF(swig_obj[i + %d]);\n", num_arguments); + Printf(f->code, "varargs = PyTuple_New(nobjs > %d ? nobjs - %d : 0);\n", num_fixed_arguments, num_fixed_arguments); + Printf(f->code, "for (i = 0; i < nobjs - %d; ++i) {\n", num_fixed_arguments); + Printf(f->code, " PyTuple_SET_ITEM(newargs, i, swig_obj[i + %d]);\n", num_fixed_arguments); + 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_arguments); - Printf(f->code, "varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_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)+1);\n", num_fixed_arguments); } Printf(f->code, "resultobj = %s__varargs__(%s,newargs,varargs);\n", wname, builtin ? "self" : "NULL"); Append(f->code, "Py_XDECREF(newargs);\n");