diff --git a/SWIG/Lib/python/pyclasses.swg b/SWIG/Lib/python/pyclasses.swg new file mode 100644 index 000000000..cf6d9ddb7 --- /dev/null +++ b/SWIG/Lib/python/pyclasses.swg @@ -0,0 +1,128 @@ +#ifdef __cplusplus + +/* + PyObject_ptr is used as a replacement of PyObject *, where + the INCREF/DECREF are applied as needed. + + You can use PyObject_ptr in a container, such as + + std::vector; + + or as a member variable: + + struct A { + PyObject_ptr obj; + A(PyObject *o) : _obj(o) { + } + }; + + or as a input/output value + + PyObject_ptr func(PyObject_ptr obj) { + PyObject_ptr out = PyString_FromFormat("hello %s", PyObject_AsString(obj)); + Py_DECREF(out); + return out; + } + + just remember to pair the object creation with the proper DECREF, + the same as with plain PyObject *ptr, since PyObject_ptr always add + one reference at construction. + + PyObject_ptr is 'visible' at the wrapped side, so you can do: + + + %template(pyvector) std::vector; + + and all the proper typemaps will be used. + +*/ + +namespace swig { + %ignore PyObject_ptr; + struct PyObject_ptr {}; + %apply PyObject * {PyObject_ptr}; + %apply PyObject * const& {PyObject_ptr const&}; +} + +%{ +namespace swig { + class PyObject_ptr { + protected: + PyObject *_obj; + + public: + PyObject_ptr() :_obj(0) + { + } + + PyObject_ptr(const PyObject_ptr& item) : _obj(item._obj) + { + Py_XINCREF(_obj); + } + + PyObject_ptr(PyObject *obj, bool initial_ref = true) :_obj(obj) + { + if (initial_ref) Py_XINCREF(_obj); + } + + PyObject_ptr & operator=(const PyObject_ptr& item) + { + Py_XINCREF(item._obj); + Py_XDECREF(_obj); + _obj = item._obj; + return *this; + } + + ~PyObject_ptr() + { + Py_XDECREF(_obj); + } + + operator PyObject *() const + { + return _obj; + } + + PyObject *operator->() const + { + return _obj; + } + }; +} +%} + +/* + PyObject_var is used to manage 'in the scope' PyObject * variables, + as in + + int func () { + PyObject_var obj = PyString_FromString("hello"); + } + + ie, 'obj' is created and destructed in the same scope from + a python object that carries at least one reference value. + + PyObject_var just take care of applying the proper Py_DECREF. + + Hence, this class is purely internal and not visible at the wrapped side. + */ +%{ + namespace swig { + struct PyObject_var : PyObject_ptr { + PyObject_var(PyObject* obj = 0) : PyObject_ptr(obj, false) { } + + PyObject_var & operator = (PyObject* obj) + { + Py_XDECREF(_obj); + _obj = obj; + return *this; + } + }; + } +%} + + + + + +#endif diff --git a/SWIG/Lib/python/pycontainer.swg b/SWIG/Lib/python/pycontainer.swg index e1e64598a..9008d7538 100644 --- a/SWIG/Lib/python/pycontainer.swg +++ b/SWIG/Lib/python/pycontainer.swg @@ -24,76 +24,17 @@ %include std_except.i - - -namespace swig { - %ignore PyItem; - struct PyItem {}; - %apply PyObject * {PyItem}; - %apply PyObject * const& {PyItem const&}; -} - -%{ -namespace swig { - class PyItem { - PyObject *_obj; - public: - PyItem() :_obj(0) - { - } - - PyItem(const PyItem& item) : _obj(item._obj) - { - Py_XINCREF(_obj); - } - - PyItem(PyObject *obj) :_obj(obj) - { - Py_XINCREF(_obj); - } - - PyItem & operator=(PyObject *obj) { - Py_XINCREF(obj); - Py_XDECREF(_obj); - _obj = obj; - return *this; - } - - PyItem & operator=(const PyItem& item) { - this->operator=(static_cast(item)); - return *this; - } - - ~PyItem() - { - if (_obj) Py_DECREF(_obj); - } - - operator PyObject *() const - { - return _obj; - } - - PyObject *operator->() const - { - return _obj; - } - - }; -} -%} - -%fragment(SWIG_Traits_frag(swig::PyItem),"header",fragment="StdTraits") { +%fragment(SWIG_Traits_frag(swig::PyObject_ptr),"header",fragment="StdTraits") { namespace swig { - template <> struct traits { + template <> struct traits { typedef value_category category; - static const char* type_name() { return "PyItem"; } + static const char* type_name() { return "PyObject_ptr"; } }; - template <> struct traits_from { - typedef PyItem value_type; + template <> struct traits_from { + typedef PyObject_ptr value_type; static PyObject *from(const value_type& val) { PyObject *obj = static_cast(val); Py_XINCREF(obj); @@ -102,14 +43,14 @@ namespace swig { }; template <> - struct traits_check { + struct traits_check { static bool check(PyObject *) { return true; } }; - template <> struct traits_asval { - typedef PyItem value_type; + template <> struct traits_asval { + typedef PyObject_ptr value_type; static int asval(PyObject *obj, value_type *val) { if (val) *val = obj; return SWIG_OK; @@ -132,10 +73,10 @@ namespace std { }; template <> - struct less : public binary_function + struct less : public binary_function { bool - operator()(const swig::PyItem& v, const swig::PyItem& w) const + operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const { return PyObject_Compare(v, w) < 0; } }; } @@ -297,7 +238,7 @@ namespace swig { struct PySequence_OutputIterator { private: - PyItem _seq; + PyObject_ptr _seq; protected: PySequence_OutputIterator(PyObject *seq) : _seq(seq) @@ -380,8 +321,7 @@ namespace swig { %fragment("PySequence_Cont","header", fragment="StdTraits", - fragment="PySequence_Base", - fragment="PyObject_var") + fragment="PySequence_Base") { #include @@ -875,7 +815,7 @@ namespace swig // %fragment("StdSequenceTraits","header", - fragment="StdTraits",fragment="PyObject_var", + fragment="StdTraits", fragment="PySequence_Cont") { namespace swig { diff --git a/SWIG/Lib/python/pystdcommon.swg b/SWIG/Lib/python/pystdcommon.swg index 8f23c2685..b56249791 100644 --- a/SWIG/Lib/python/pystdcommon.swg +++ b/SWIG/Lib/python/pystdcommon.swg @@ -1,16 +1,3 @@ -%fragment("PyObject_var","header") -{ - namespace swig { - struct PyObject_var { - PyObject* ptr; - PyObject_var(PyObject* obj = 0) : ptr(obj) { } - ~PyObject_var() { if (ptr) Py_DECREF(ptr); } - operator PyObject*() { return ptr; } - PyObject* operator->() const { return ptr; } - }; - } -} - %fragment("StdTraits","header",fragment="StdTraitsCommon") { namespace swig { diff --git a/SWIG/Lib/python/python.swg b/SWIG/Lib/python/python.swg index 3b22579f6..052bd0696 100644 --- a/SWIG/Lib/python/python.swg +++ b/SWIG/Lib/python/python.swg @@ -44,9 +44,15 @@ * ------------------------------------------------------------ */ %include +/* ------------------------------------------------------------ + * The Python classes, for C++ + * ------------------------------------------------------------ */ +%include + /* ------------------------------------------------------------ * The Python initialization function * ------------------------------------------------------------ */ %include + diff --git a/SWIG/Lib/python/std_pair.i b/SWIG/Lib/python/std_pair.i index aab386533..af159ff31 100644 --- a/SWIG/Lib/python/std_pair.i +++ b/SWIG/Lib/python/std_pair.i @@ -3,8 +3,7 @@ */ %include -%fragment("StdPairTraits","header", - fragment="StdTraits",fragment="PyObject_var") { +%fragment("StdPairTraits","header",fragment="StdTraits") { namespace swig { template struct traits_asptr > {