add swig::PyItem and all the helper code
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7787 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
c655b7d1be
commit
04113db0e7
7 changed files with 206 additions and 6 deletions
|
|
@ -1,6 +1,76 @@
|
||||||
Unreleased changes
|
Unreleased changes
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
11/02/2005: mmatus
|
||||||
|
|
||||||
|
[Python] Adding more fun to STL/STD containers, now you
|
||||||
|
can do
|
||||||
|
|
||||||
|
%template(pyset) std::set<PyObject *>;
|
||||||
|
%template(pyvector) std::vector<PyObject *>;
|
||||||
|
%template() std::pair<PyObject *,PyObject *>;
|
||||||
|
%template(pyvector) std::map<PyObject *,PyObject *>;
|
||||||
|
....
|
||||||
|
|
||||||
|
The same applies to std::list, std::deque, std::multiset, etc.
|
||||||
|
|
||||||
|
Then, at the python side you can do now:
|
||||||
|
|
||||||
|
# C++ std::vector as native python sequence
|
||||||
|
v = pyvector([1,"hello",(1,2)])
|
||||||
|
print v[1]
|
||||||
|
>> 'hello'
|
||||||
|
print v[2]
|
||||||
|
>> (1,2)
|
||||||
|
|
||||||
|
# C++ std::set as native python sequence
|
||||||
|
s = pyset()
|
||||||
|
s.insert((1,2))
|
||||||
|
s.insert(1)
|
||||||
|
s.insert("hello")
|
||||||
|
sum=()
|
||||||
|
for i in s:
|
||||||
|
sum +=(i,)
|
||||||
|
print sum
|
||||||
|
>>> (1, 'hello', (1, 2))
|
||||||
|
|
||||||
|
# C++ std::map as native python sequence
|
||||||
|
m = pymap()
|
||||||
|
m["foo"] = "hello"
|
||||||
|
m[1] = (1,2)
|
||||||
|
pm = {}
|
||||||
|
for k in m:
|
||||||
|
pm[k] = m[k]
|
||||||
|
print pm
|
||||||
|
>>> {1: (1, 2), 'foo': 'hello'}
|
||||||
|
|
||||||
|
ie, the STD/STL containers work as real native python
|
||||||
|
container, with arbitrary item types and so.
|
||||||
|
|
||||||
|
But since normal C++ containers do not properly ref/unref
|
||||||
|
their items, you should use the safer versions:
|
||||||
|
|
||||||
|
%template(pyset) std::set<swig::PyItem>;
|
||||||
|
%template(pyvector) std::vector<swig::PyItem>;
|
||||||
|
%template() std::pair<swig::PyItem, swig::PyItem>;
|
||||||
|
%template(pyvector) std::map<swig::PyItem,swig::PyItem>;
|
||||||
|
....
|
||||||
|
|
||||||
|
where swig::PyItem is a PyObject * envelope class provided
|
||||||
|
to safely incref/decref the python object.
|
||||||
|
|
||||||
|
So, now you can use all the STL/STD containers as native
|
||||||
|
Python containers.
|
||||||
|
|
||||||
|
Note 1: std::map, std::set and the other 'ordered'
|
||||||
|
containers will properly use PyObject_Compare for sorting,
|
||||||
|
when needed.
|
||||||
|
|
||||||
|
Note 2: all the STL/STD containers have a limit size of
|
||||||
|
SIZE_MAX, ie, you can have manage containers larger than
|
||||||
|
INT_MAX, the python limit.
|
||||||
|
|
||||||
|
|
||||||
11/02/2005: mmatus
|
11/02/2005: mmatus
|
||||||
|
|
||||||
[Python]
|
[Python]
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ namespace std
|
||||||
%template(pairiiAc) pair<int,const pair<int, A*> >;
|
%template(pairiiAc) pair<int,const pair<int, A*> >;
|
||||||
|
|
||||||
|
|
||||||
%template() pair<PyObject *, PyObject *>;
|
%template() pair<swig::PyItem, swig::PyItem>;
|
||||||
%template(pymap) map<PyObject *, PyObject*>;
|
%template(pymap) map<swig::PyItem, swig::PyItem>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,17 @@ for k in m:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
m = {}
|
||||||
|
m[1] = (1,2)
|
||||||
|
m["foo"] = "hello"
|
||||||
|
|
||||||
pm = li_std_map.pymap()
|
pm = li_std_map.pymap()
|
||||||
|
|
||||||
pm[1] = (1,2)
|
for k in m:
|
||||||
pm["foo"] = "hello"
|
pm[k] = m[k]
|
||||||
|
|
||||||
for k in pm:
|
for k in pm:
|
||||||
print pm[k]
|
if (pm[k] != m[k]):
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,5 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%template(pyset) std::set<swig::PyItem>;
|
||||||
|
|
|
||||||
|
|
@ -82,3 +82,15 @@ if m.value() != "c":
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
s = pyset()
|
||||||
|
s.insert((1,2))
|
||||||
|
s.insert(1)
|
||||||
|
s.insert("hello")
|
||||||
|
|
||||||
|
|
||||||
|
sum = ()
|
||||||
|
for i in s:
|
||||||
|
sum += (i,)
|
||||||
|
|
||||||
|
if sum != (1, 'hello', (1, 2)):
|
||||||
|
raise RuntimeError
|
||||||
|
|
|
||||||
|
|
@ -123,4 +123,4 @@ std::vector<std::string> vecStr(std::vector<std::string> v) {
|
||||||
%array_functions(int,ArrInt)
|
%array_functions(int,ArrInt)
|
||||||
|
|
||||||
|
|
||||||
%template(pyvector) std::vector<PyObject*>;
|
%template(pyvector) std::vector<swig::PyItem>;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,64 @@
|
||||||
|
|
||||||
%include std_except.i
|
%include std_except.i
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace swig {
|
||||||
|
%ignore PyItem;
|
||||||
|
struct PyItem {};
|
||||||
|
%apply PyObject * {PyItem};
|
||||||
|
%apply PyObject * const& {PyItem const&};
|
||||||
|
}
|
||||||
|
|
||||||
|
%fragment(SWIG_Traits_frag(swig::PyItem),"header",fragment="StdTraits") {
|
||||||
|
namespace swig {
|
||||||
|
template <> struct traits<PyItem > {
|
||||||
|
typedef value_category category;
|
||||||
|
static const char* type_name() { return "PyItem"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct traits_from<PyItem> {
|
||||||
|
typedef PyItem value_type;
|
||||||
|
static PyObject *from(const value_type& val) {
|
||||||
|
return static_cast<PyObject *>(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct traits_check<PyItem, value_category> {
|
||||||
|
static bool check(PyObject *obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct traits_asval<PyItem > {
|
||||||
|
typedef PyItem value_type;
|
||||||
|
static int asval(PyObject *obj, value_type *val) {
|
||||||
|
if (val) *val = obj;
|
||||||
|
return SWIG_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%fragment(SWIG_Traits_frag(PyItem),"header")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
%fragment("PySequence_Base","header")
|
%fragment("PySequence_Base","header")
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct less <PyObject *>: public binary_function<PyObject *, PyObject *, bool>
|
||||||
|
{
|
||||||
|
bool
|
||||||
|
operator()(PyObject * v, PyObject *w) const
|
||||||
|
{ return PyObject_Compare(v, w) < 0; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace swig {
|
namespace swig {
|
||||||
template <> struct traits<PyObject *> {
|
template <> struct traits<PyObject *> {
|
||||||
typedef value_category category;
|
typedef value_category category;
|
||||||
|
|
@ -45,6 +101,59 @@ namespace swig {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PyItem {
|
||||||
|
PyObject *_obj;
|
||||||
|
public:
|
||||||
|
PyItem(const PyItem& item) : _obj(item._obj)
|
||||||
|
{
|
||||||
|
Py_XINCREF(_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyItem(PyObject *obj = 0) :_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<PyObject *>(item));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~PyItem()
|
||||||
|
{
|
||||||
|
Py_XDECREF(_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator PyObject *() const
|
||||||
|
{
|
||||||
|
return _obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *operator->() const
|
||||||
|
{
|
||||||
|
return _obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct less <swig::PyItem>: public binary_function<swig::PyItem, swig::PyItem, bool>
|
||||||
|
{
|
||||||
|
bool
|
||||||
|
operator()(const swig::PyItem& v, const swig::PyItem& w) const
|
||||||
|
{ return PyObject_Compare(v, w) < 0; }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace swig {
|
namespace swig {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue