From: <sz...@us...> - 2010-12-14 21:11:09
|
Revision: 12346 http://swig.svn.sourceforge.net/swig/?rev=12346&view=rev Author: szager Date: 2010-12-14 21:11:02 +0000 (Tue, 14 Dec 2010) Log Message: ----------- Added sequence and mapping support for builtin types. Fixed object ownership in %pyswigbinoperator. Test suite now fails on li_std_vector_extra. Modified Paths: -------------- branches/szager-python-builtin/Lib/python/builtin.swg branches/szager-python-builtin/Lib/python/pycontainer.swg branches/szager-python-builtin/Lib/python/pyopers.swg branches/szager-python-builtin/Source/Modules/python.cxx Modified: branches/szager-python-builtin/Lib/python/builtin.swg =================================================================== --- branches/szager-python-builtin/Lib/python/builtin.swg 2010-12-14 00:08:45 UTC (rev 12345) +++ branches/szager-python-builtin/Lib/python/builtin.swg 2010-12-14 21:11:02 UTC (rev 12346) @@ -1,18 +1,99 @@ -extern int -pyswig_setter_closure (PyObject *obj, PyObject *val, void *closure) -{ - if (!closure) - return -1; - PyObject *tuple = PyTuple_New(1); - assert(tuple); - PyTuple_SET_ITEM(tuple, 0, val); - Py_XINCREF(val); - PyObject *result = ((PyCFunction) closure)(obj, tuple); - Py_DECREF(tuple); - Py_XDECREF(result); - return result ? 0 : -1; +#define PYSWIG_BINARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject* \ +wrapper##_closure (PyObject *a, PyObject *b) \ +{ \ + PyObject *tuple = PyTuple_New(1); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, b); \ + Py_XINCREF(b); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ } +#define PYSWIG_TERNARYFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject* \ +wrapper##_closure (PyObject *a, PyObject *b, PyObject *c) \ +{ \ + PyObject *tuple = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, b); \ + PyTuple_SET_ITEM(tuple, 1, c); \ + Py_XINCREF(b); \ + Py_XINCREF(c); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ +} + +#define PYSWIG_LENFUNC_CLOSURE(wrapper) \ +SWIGINTERN Py_ssize_t \ +wrapper##_closure (PyObject *a) \ +{ \ + PyObject *resultobj = wrapper(a, NULL); \ + Py_ssize_t result = _PyLong_AsSsize_t(resultobj); \ + Py_DECREF(resultobj); \ + return result; \ +} + +#define PYSWIG_SSIZESSIZEARGFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject* \ +wrapper##_closure (PyObject *a, Py_ssize_t b, Py_ssize_t c) \ +{ \ + PyObject *tuple = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ +} + +#define PYSWIG_SSIZESSIZEOBJARGPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_closure (PyObject *a, Py_ssize_t b, Py_ssize_t c, PyObject *d) \ +{ \ + PyObject *tuple = PyTuple_New(3); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyTuple_SET_ITEM(tuple, 1, _PyLong_FromSsize_t(c)); \ + PyTuple_SET_ITEM(tuple, 2, d); \ + Py_XINCREF(d); \ + PyObject *resultobj = wrapper(a, tuple); \ + int result = resultobj ? 0 : -1; \ + Py_DECREF(tuple); \ + Py_XDECREF(resultobj); \ + return result; \ +} + +#define PYSWIG_SSIZEARGFUNC_CLOSURE(wrapper) \ +SWIGINTERN PyObject* \ +wrapper##_closure (PyObject *a, Py_ssize_t b) \ +{ \ + PyObject *tuple = PyTuple_New(1); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyObject *result = wrapper(a, tuple); \ + Py_DECREF(tuple); \ + return result; \ +} + +#define PYSWIG_SSIZEOBJARGPROC_CLOSURE(wrapper) \ +SWIGINTERN int \ +wrapper##_closure (PyObject *a, Py_ssize_t b, PyObject *c) \ +{ \ + PyObject *tuple = PyTuple_New(2); \ + assert(tuple); \ + PyTuple_SET_ITEM(tuple, 0, _PyLong_FromSsize_t(b)); \ + PyTuple_SET_ITEM(tuple, 1, c); \ + Py_XINCREF(c); \ + PyObject *resultobj = wrapper(a, tuple); \ + int result = resultobj ? 0 : -1; \ + Py_XDECREF(resultobj); \ + Py_DECREF(tuple); \ + return result; \ +} + #ifdef __cplusplus namespace { @@ -27,6 +108,8 @@ static PyMethodDef methods[]; static PyGetSetDef getset[]; static PyNumberMethods number_methods; + static PySequenceMethods sequence_methods; + static PyMappingMethods mapping_methods; static PyTypeObject pytype; static SwigPyClientData clientdata; }; @@ -40,29 +123,21 @@ (*pyobj->ob_type->tp_free)(pyobj); } -template <PyCFunction func> PyObject* -pyswig_binaryfunc_closure (PyObject *a, PyObject *b) +SWIGINTERN int +pyswig_setter_closure (PyObject *obj, PyObject *val, void *closure) { + if (!closure) + return -1; PyObject *tuple = PyTuple_New(1); assert(tuple); - PyTuple_SET_ITEM(tuple, 0, b); - PyObject *result = func(a, tuple); + PyTuple_SET_ITEM(tuple, 0, val); + Py_XINCREF(val); + PyObject *result = ((PyCFunction) closure)(obj, tuple); Py_DECREF(tuple); - return result; + Py_XDECREF(result); + return result ? 0 : -1; } -template <PyCFunction func> PyObject* -pyswig_ternaryfunc_closure (PyObject *a, PyObject *b, PyObject *c) -{ - PyObject *tuple = PyTuple_New(2); - assert(tuple); - PyTuple_SET_ITEM(tuple, 0, b); - PyTuple_SET_ITEM(tuple, 1, c); - PyObject *result = func(a, tuple); - Py_DECREF(tuple); - return result; -} - } // namespace { #endif Modified: branches/szager-python-builtin/Lib/python/pycontainer.swg =================================================================== --- branches/szager-python-builtin/Lib/python/pycontainer.swg 2010-12-14 00:08:45 UTC (rev 12345) +++ branches/szager-python-builtin/Lib/python/pycontainer.swg 2010-12-14 21:11:02 UTC (rev 12346) @@ -599,7 +599,6 @@ /**** The python container methods ****/ - %define %swig_container_methods(Container...) %newobject __getslice__; @@ -618,8 +617,16 @@ return self->size(); } } + +#if defined(SWIGPYTHON_BUILTIN) +%pybinoperator(__nonzero__, __nonzero__, unaryfunc, nb_nonzero); +%pybinoperator(__len__, __len__, lenfunc, sq_length); +#endif // SWIGPYTHON_BUILTIN + %enddef + + %define %swig_sequence_methods_common(Sequence...) %swig_sequence_iterator(%arg(Sequence)) %swig_container_methods(%arg(Sequence)) @@ -697,6 +704,14 @@ } } + +#if defined(SWIGPYTHON_BUILTIN) +%pybinoperator(__getitem__, __getitem__, ssizeargfunc, sq_item); +%pybinoperator(__getslice__, __getslice__, ssizessizeargfunc, sq_slice); +%pybinoperator(__setitem__, __setitem__, ssizeobjargproc, sq_ass_item); +%pybinoperator(__setslice__, __setslice__, ssizessizeobjargproc, sq_ass_slice); +#endif // SWIGPYTHON_BUILTIN + %enddef %define %swig_sequence_methods(Sequence...) @@ -714,6 +729,7 @@ self->push_back(x); } } + %enddef %define %swig_sequence_methods_val(Sequence...) @@ -731,6 +747,7 @@ self->push_back(x); } } + %enddef Modified: branches/szager-python-builtin/Lib/python/pyopers.swg =================================================================== --- branches/szager-python-builtin/Lib/python/pyopers.swg 2010-12-14 00:08:45 UTC (rev 12345) +++ branches/szager-python-builtin/Lib/python/pyopers.swg 2010-12-14 21:11:02 UTC (rev 12346) @@ -13,20 +13,20 @@ #define %pycompare(pyname,oper,comptype) %pybinoperator(pyname,oper,,comptype) #endif -%pybinoperator(__add__, *::operator+, binary_func, nb_add); -%pybinoperator(__pos__, *::operator+(), unary_func, nb_positive); -%pybinoperator(__pos__, *::operator+() const, unary_func, nb_positive); -%pybinoperator(__sub__, *::operator-, binary_func, nb_subtract); -%pybinoperator(__neg__, *::operator-(), unary_func, nb_negative); -%pybinoperator(__neg__, *::operator-() const, unary_func, nb_negative); -%pybinoperator(__mul__, *::operator*, binary_func, nb_multiply); -%pybinoperator(__div__, *::operator/, binary_func, nb_div); -%pybinoperator(__mod__, *::operator%, binary_func, nb_remainder); -%pybinoperator(__lshift__, *::operator<<, binary_func, nb_lshift); -%pybinoperator(__rshift__, *::operator>>, binary_func, nb_rshift); -%pybinoperator(__and__, *::operator&, binary_func, nb_and); -%pybinoperator(__or__, *::operator|, binary_func, nb_or); -%pybinoperator(__xor__, *::operator^, binary_func, nb_xor); +%pybinoperator(__add__, *::operator+, binaryfunc, nb_add); +%pybinoperator(__pos__, *::operator+(), unaryfunc, nb_positive); +%pybinoperator(__pos__, *::operator+() const, unaryfunc, nb_positive); +%pybinoperator(__sub__, *::operator-, binaryfunc, nb_subtract); +%pybinoperator(__neg__, *::operator-(), unaryfunc, nb_negative); +%pybinoperator(__neg__, *::operator-() const, unaryfunc, nb_negative); +%pybinoperator(__mul__, *::operator*, binaryfunc, nb_multiply); +%pybinoperator(__div__, *::operator/, binaryfunc, nb_div); +%pybinoperator(__mod__, *::operator%, binaryfunc, nb_remainder); +%pybinoperator(__lshift__, *::operator<<, binaryfunc, nb_lshift); +%pybinoperator(__rshift__, *::operator>>, binaryfunc, nb_rshift); +%pybinoperator(__and__, *::operator&, binaryfunc, nb_and); +%pybinoperator(__or__, *::operator|, binaryfunc, nb_or); +%pybinoperator(__xor__, *::operator^, binaryfunc, nb_xor); %pycompare(__lt__, *::operator<, Py_LT); %pycompare(__le__, *::operator<=, Py_LE); %pycompare(__gt__, *::operator>, Py_GT); @@ -34,16 +34,16 @@ %pycompare(__eq__, *::operator==, Py_EQ); %pycompare(__ne__, *::operator!=, Py_NE); -%feature("pyslot", "nb_truediv", functype="binary_func") *::operator/; +%feature("pyslot", "nb_truediv", functype="binaryfunc") *::operator/; /* Special cases */ %rename(__invert__) *::operator~; -%feature("pyslot", "nb_invert", functype="unary_func") *::operator~; +%feature("pyslot", "nb_invert", functype="unaryfunc") *::operator~; %rename(__call__) *::operator(); -%feature("pyslot", "tp_call", functype="ternary_func") *::operator(); +%feature("pyslot", "tp_call", functype="ternaryfunc") *::operator(); #if defined(SWIGPYTHON_BUILTIN) -%pybinoperator(__nonzero__, *::operator bool, unary_func, nb_nonzero); +%pybinoperator(__nonzero__, *::operator bool, unaryfunc, nb_nonzero); #else %feature("shadow") *::operator bool %{ def __nonzero__(self): @@ -103,21 +103,21 @@ */ #if defined(SWIGPYTHON_BUILTIN) -#define %pyinplaceoper(SwigPyOper, Oper, functp, slot) %rename(SwigPyOper) Oper; %feature("pyslot", #slot, functype=#functp) Oper; +#define %pyinplaceoper(SwigPyOper, Oper, functp, slot) %delobject Oper; %newobject Oper; %feature("pyslot", #slot, functype=#functp) Oper; %rename(SwigPyOper) Oper #else #define %pyinplaceoper(SwigPyOper, Oper, functp, slot) %delobject Oper; %newobject Oper; %rename(SwigPyOper) Oper #endif -%pyinplaceoper(__iadd__ , *::operator +=, binary_func, nb_inplace_add); -%pyinplaceoper(__isub__ , *::operator -=, binary_func, nb_inplace_subtract); -%pyinplaceoper(__imul__ , *::operator *=, binary_func, nb_inplace_multiply); -%pyinplaceoper(__idiv__ , *::operator /=, binary_func, nb_inplace_divide); -%pyinplaceoper(__imod__ , *::operator %=, binary_func, nb_inplace_remainder); -%pyinplaceoper(__iand__ , *::operator &=, binary_func, nb_inplace_and); -%pyinplaceoper(__ior__ , *::operator |=, binary_func, nb_inplace_or); -%pyinplaceoper(__ixor__ , *::operator ^=, binary_func, nb_inplace_xor); -%pyinplaceoper(__ilshift__, *::operator <<=, binary_func, nb_inplace_lshift); -%pyinplaceoper(__irshift__, *::operator >>=, binary_func, nb_inplace_rshift); +%pyinplaceoper(__iadd__ , *::operator +=, binaryfunc, nb_inplace_add); +%pyinplaceoper(__isub__ , *::operator -=, binaryfunc, nb_inplace_subtract); +%pyinplaceoper(__imul__ , *::operator *=, binaryfunc, nb_inplace_multiply); +%pyinplaceoper(__idiv__ , *::operator /=, binaryfunc, nb_inplace_divide); +%pyinplaceoper(__imod__ , *::operator %=, binaryfunc, nb_inplace_remainder); +%pyinplaceoper(__iand__ , *::operator &=, binaryfunc, nb_inplace_and); +%pyinplaceoper(__ior__ , *::operator |=, binaryfunc, nb_inplace_or); +%pyinplaceoper(__ixor__ , *::operator ^=, binaryfunc, nb_inplace_xor); +%pyinplaceoper(__ilshift__, *::operator <<=, binaryfunc, nb_inplace_lshift); +%pyinplaceoper(__irshift__, *::operator >>=, binaryfunc, nb_inplace_rshift); /* Finally, in python we need to mark the binary operations to fail as Modified: branches/szager-python-builtin/Source/Modules/python.cxx =================================================================== --- branches/szager-python-builtin/Source/Modules/python.cxx 2010-12-14 00:08:45 UTC (rev 12345) +++ branches/szager-python-builtin/Source/Modules/python.cxx 2010-12-14 21:11:02 UTC (rev 12346) @@ -172,7 +172,31 @@ return val ? val : slot_default; } +static String* +getClosure (String *functype, String *wrapper) +{ + static const char *functypes[] = { + "binaryfunc", "PYSWIG_BINARYFUNC_CLOSURE", + "ternaryfunc", "PYSWIG_TERNARYFUNC_CLOSURE", + "lenfunc", "PYSWIG_LENFUNC_CLOSURE", + "ssizeargfunc", "PYSWIG_SSIZEARGFUNC_CLOSURE", + "ssizessizeargfunc", "PYSWIG_SSIZESSIZEARGFUNC_CLOSURE", + "ssizeobjargproc", "PYSWIG_SSIZEOBJARGPROC_CLOSURE", + "ssizessizeobjargproc", "PYSWIG_SSIZESSIZEOBJARGPROC_CLOSURE", + NULL + }; + if (!functype) + return NULL; + char *c = Char(functype); + int i; + for (i = 0; functypes[i] != NULL; i += 2) { + if (!strcmp(c, functypes[i])) + return NewStringf("%s(%s)", functypes[i+1], wrapper); + } + return NULL; +} + class PYTHON:public Language { public: PYTHON() { @@ -1947,18 +1971,18 @@ char const *self_param = builtin_self ? "self" : "SWIGUNUSEDPARM(self)"; char const *wrap_return = builtin_ctor ? "int " : "PyObject *"; String *linkage = NewString("SWIGINTERN "); + String *wrapper_name = Swig_name_wrapper(iname); String *slot = Getattr(n, "feature:pyslot"); + String *closure_decl = NULL; + if (slot) + closure_decl = getClosure(Getattr(n, "feature:pyslot:functype"), wrapper_name); + + /* if (builtin_setter || builtin_getter) { Clear(linkage); Printv(linkage, "extern ", NIL); } - if (slot) { - String *functype = Getattr(n, "feature:pyslot:functype"); - if (!strcmp(Char(functype), "binary_func") || !strcmp(Char(functype), "ternary_func")) { - Clear(linkage); - Printv(linkage, "extern ", NIL); - } - } + */ if (Getattr(n, "sym:overloaded")) { overname = Getattr(n, "sym:overname"); @@ -2000,7 +2024,7 @@ allow_kwargs = 0; varargs = emit_isvarargs(l); - String *wname = Swig_name_wrapper(iname); + String *wname = Copy(wrapper_name); if (overname) { Append(wname, overname); } @@ -2510,8 +2534,6 @@ } } - String *wrapper_name = Swig_name_wrapper(iname); - /* If this is a builtin type, create a PyGetSetDef entry for this member variable. */ if (builtin_getter) { Hash *h = Getattr(builtin_getset, name); @@ -2534,15 +2556,12 @@ /* Handle builtin operator overloads */ if (slot) { - String *functype = Getattr(n, "feature:pyslot:functype"); String *feature_name = NewStringf("feature:%s", slot); - String *closure_name = NewString(""); - if (!strcmp(Char(functype), "binary_func")) { - Printf(closure_name, "pyswig_binaryfunc_closure< %s >", wrapper_name); - } else if (!strcmp(Char(functype), "ternary_func")) { - Printf(closure_name, "pyswig_ternaryfunc_closure< %s >", wrapper_name); - } else { - Append(closure_name, wrapper_name); + String *closure_name = Copy(wrapper_name); + if (closure_decl) { + if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling")) + Printv(f_wrappers, closure_decl, "\n\n", NIL); + Append(closure_name, "_closure"); } Node *parent = Swig_methodclass(n); Setattr(parent, feature_name, closure_name); @@ -2561,6 +2580,8 @@ Delete(wname); DelWrapper(f); Delete(wrapper_name); + if (closure_decl) + Delete(closure_decl); return SWIG_OK; } @@ -3123,6 +3144,25 @@ Printf(f, " (unaryfunc) %s, // nb_index;\n", getSlot(n, "feature:nb_index")); Printf(f, "};\n\n"); + Printf(f, "template <> PySequenceMethods PySwigBuiltin< %s >::sequence_methods = {\n", rname); + Printf(f, " (lenfunc) %s, // sq_length\n", getSlot(n, "sq_length")); + Printf(f, " (binaryfunc) %s, // sq_concat\n", getSlot(n, "sq_concat")); + Printf(f, " (ssizeargfunc) %s, // sq_repeat\n", getSlot(n, "sq_repeat")); + Printf(f, " (ssizeargfunc) %s, // sq_item\n", getSlot(n, "sq_item")); + Printf(f, " (ssizessizeargfunc) %s, // sq_slice\n", getSlot(n, "sq_slice")); + Printf(f, " (ssizeobjargproc) %s, // sq_ass_item\n", getSlot(n, "sq_ass_item")); + Printf(f, " (ssizessizeobjargproc) %s, // sq_ass_slice\n", getSlot(n, "sq_ass_slice")); + Printf(f, " (objobjproc) %s, // sq_contains\n", getSlot(n, "sq_contains")); + Printf(f, " (binaryfunc) %s, // sq_inplace_concat\n", getSlot(n, "sq_inplace_concat")); + Printf(f, " (ssizeargfunc) %s, // sq_inplace_repeat\n", getSlot(n, "sq_inplace_repeat")); + Printf(f, "};\n\n"); + + Printf(f, "template <> PyMappingMethods PySwigBuiltin< %s >::mapping_methods = {\n", rname); + Printf(f, " (lenfunc) %s, // mp_length;\n", getSlot(n, "mp_length")); + Printf(f, " (binaryfunc) %s, // mp_subscript;\n", getSlot(n, "mp_subscript")); + Printf(f, " (objobjargproc) %s, // mp_ass_subscript;\n", getSlot(n, "mp_ass_subscript")); + Printf(f, "};\n\n"); + String *tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES"); // TODO: Add more flags based on slots Printf(f, "template <> PyTypeObject PySwigBuiltin< %s >::pytype = {\n", rname); @@ -3138,8 +3178,8 @@ Printf(f, " %s, /*tp_compare*/\n", getSlot(n, "feature:tp_compare")); Printf(f, " %s, /*tp_repr*/\n", getSlot(n, "feature:tp_repr")); Printf(f, " &%s::number_methods, /*tp_as_number*/\n", templ); - Printf(f, " %s, /*tp_as_sequence*/\n", getSlot(n, "feature:tp_as_sequence")); - Printf(f, " %s, /*tp_as_mapping*/\n", getSlot(n, "feature:tp_as_mapping")); + Printf(f, " &%s::sequence_methods, /*tp_as_sequence*/\n", templ); + Printf(f, " &%s::mapping_methods, /*tp_as_mapping*/\n", templ); Printf(f, " %s, /*tp_hash */\n", getSlot(n, "feature:tp_hash")); Printf(f, " %s, /*tp_call*/\n", getSlot(n, "feature:tp_call")); Printf(f, " %s, /*tp_str*/\n", getSlot(n, "feature:tp_str")); @@ -3519,8 +3559,6 @@ String *fullname = Swig_name_member(NULL, class_name, symname); String *wname = Swig_name_wrapper(fullname); Setattr(class_members, name, name); - ParmList *parms = Getattr(n, "parms"); - bool noArgs = !parms || Len(parms) == 0; String *pyflags = NewString("METH_VARARGS"); Printf(f_shadow, " { \"%s\", (PyCFunction) %s, %s, \"\" },\n", Char(name), wname, Char(pyflags)); Delete(name); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |