Segfault when calling python method from C++
I have an embedded python in a C++ program. I extend python using boost in order to interact with C++. Some of my methods makes use of C++ function-object. So I implemented this class to encapsulate Python methods : ***************************************************** struct PyCenterComp { PyCenterComp( boost::python::object o ); PyCenterComp( const PyCenterComp& copy ); vertex_type operator()( Delaunay2D::cell_descriptor cell ); boost::python::object method; }; PyCenterComp::PyCenterComp( object o ) : method( o ) { } PyCenterComp::PyCenterComp( const PyCenterComp& copy ) : method( copy.method ) { } vertex_type PyCenterComp::operator()( Delaunay2D::cell_descriptor cell ) { std::cerr << "Call method ... " << endl; boost::python::object o( method( cell_descriptor( cell ) ) ); std::cerr << "Called" << endl; extract<vertex_type> v( o ); std::cerr << "Converted" << endl; if( v.check() ) { return v(); } return vertex_type(); } ******************************************* The Delaunay2D::cell_descriptor being implemented as void*, it's encapsulated in a cell_descriptor structure which is exported in Python. In the python interpreter I created a function object with this code : ******************************************* class ProdMean: def __init__(self, walls): self.walls = walls def __call__(self,cell): poly = self.walls.getCell(cell) return self.mean(poly) def mean(self, poly): dx = 1 dy = 1 for i in poly: dx = dx * i.x() dy = dy * i.y() dx = dx ** (1.0/len(poly)) dy = dy ** (1.0/len(poly)) return vertex_type(dx,dy) ******************************************* Then I can use this class with : p = ProdMean(walls) l = [p(i) for i in walls] walls is a C++ object (a graph) and the getCell method returns a polygon (a vector of vertex). This little python code works well. But now, if I try to call p from C++ using the PyCenterComp object I get a segmentation fault when calling the method (I got this output: Call method ... zsh: segmentation fault ) If you want, I can give you the callstack when the crash occure, but it's quite huge (~50 elements ... ) so I'll do only if it's needed. Thanks, -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68
Some more details ... I made some experiment and it appears that if I use an ob ject of the class : ****************************** class EmptyMean: def __init__(self,walls): self.walls = walls def __call__(self,cell): poly = self.walls.getCell(cell) l = len(poly) return vertex_type(l,l) *********************************** as a parameter for my C++ method, it works. But if I use : ****************************** class EmptyMean: def __init__(self,walls): self.walls = walls def __call__(self,cell): poly = self.walls.getCell(cell) return poly[0] *********************************** it crashes ! poly is an exported vector<vertex_type>. I exported it so that it has the same behaviour as a python list. Here is the code of the __getitem__ method used to export the vector to python : *************************************************************************** template <class ToExport> typename container_trait<ToExport>::value_type list_getItem(ToExport* exp, typename container_trait<ToExport>::difference_type i) { typename container_trait<ToExport>::iterator it; it = PosInRange(exp, i); return *it; } template <class ToExport> typename container_trait<ToExport>::iterator PosInRange(ToExport *l, typename container_trait<ToExport>::difference_type i) { typename container_trait<ToExport>::difference_type size = l->size(); if((i >= size) || (i < -size)) { PythonExc_IndexError ind; ind.error_str = "assignment index out of range"; throw ind; } if(i < 0) { typename container_trait<ToExport>::difference_type size = l->size(); i += size; } typename container_trait<ToExport>::iterator it = l->begin(); advance(it, i); return it; } ********************************************************************* The template parameter ToExport is here std::vector<vertex_type>. container_trait<std::vector<vertex_type> >::iterator is std::vector<vertex_type>::iterator container_trait<std::vector<vertex_type> >::difference_type is std::vector<vertex_type>::difference_type container_trait<std::vector<vertex_type> >::iterator is std::vector<vertex_type>::iterator I'm still looking for more precise information, but I still have absolutely no clue abour what is going on ... -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68
David Abrahams wrote:
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
I'm still looking for more precise information, but I still have absolutely no clue abour what is going on ...
Please post a small reproducible test case.
Ok, I did find the problem and it was on my side. My main problem was to locate it because it was within C++ code called by python code called by C++ code called by python code ... and I'm absolutely not used to debug such multi-language system ! If you want to know, the problem was in the class wrapping the cell_descriptor ... By the way, I've made some tools to export my classes, where can I submit them ? Here ? I have come classes using Qt and POSIX pipes to embed python in a C++ environment, some tools to solve Qt non-thread safe problems and templates to export STL containers (not all but most ...). Thanks anyway, -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
David Abrahams wrote:
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
I'm still looking for more precise information, but I still have absolutely no clue abour what is going on ...
Please post a small reproducible test case.
Ok, I did find the problem and it was on my side.
Works every time <wink>
My main problem was to locate it because it was within C++ code called by python code called by C++ code called by python code ... and I'm absolutely not used to debug such multi-language system ! If you want to know, the problem was in the class wrapping the cell_descriptor ...
By the way, I've made some tools to export my classes, where can I submit them ? Here ? I have come classes using Qt and POSIX pipes to embed python in a C++ environment, some tools to solve Qt non-thread safe problems and templates to export STL containers (not all but most ...).
You can post them here. After we discuss and get comfortable with your approach, the first things I'll probably ask you for are tests for the Boost.Python test suite and HTML documentation pages. Regards, -- Dave Abrahams Boost Consulting www.boost-consulting.com
You can post them here. After we discuss and get comfortable with your approach, the first things I'll probably ask you for are tests for the Boost.Python test suite and HTML documentation pages.
Regards,
Sorry for the delay but I was on vacation ... I begin by sending the three files used to export STL containers. By the time, it only works with g++-3.2 or later, but it's just a question of namespace and include locations. There is a _small_ help at the beginning. The only thing not written is for the handling of the exceptions: you have to call define_stl_exceptions() in your module function. The wcc files correspond to your hpp ones and the hh is here for tiled compilation only. My main concern about what you said is about the Boost.Python test suite ... how to document myself about how it works ? Thanks, -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68 /*************************************************************************** stl2dict.wcc - description ------------------- copyright : (C) 2003 by Pierre Barbier de Reuille email : pierre.barbier@cirad.fr ***************************************************************************/ /*************************************************************************** * * GNU General Public Licence * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ #ifndef _STL2DICT_WCC_ #define _STL2DICT_WCC_ #include <ext/hash_map> #include <map> #include <sstream> #include <iostream> using namespace std; using namespace __gnu_cxx; #include "exception.hh" /********************************** * * Notations: * * - X : container type * - a,b : container instance * - T : container data type * - u,v : container data instance * - K : container key type * - k,l : container key instance * - I : container iterator type * - i,j : container iterator instance * - os : ostream instance * * * Valid expressions for associative container : * - associative_trait<X> * - a[ k ] = u * - a.size() * - a.begin() * - a.end() * - a.empty() * - i = a.find( k ) * - n = a.erase( k ) * - a.clear() * - k = i->first * - u = i->second * - ++i * - os << k * - os << u * **********************************/ template <class Associative> struct associative_trait { typedef typename Associative::key_type key_type; typedef typename Associative::value_type value_type; typedef typename Associative::data_type data_type; typedef typename Associative::pointer pointer; typedef typename Associative::reference reference; typedef typename Associative::const_reference const_reference; typedef typename Associative::size_type size_type; typedef typename Associative::difference_type difference_type; typedef typename Associative::iterator iterator; typedef typename Associative::const_iterator const_iterator; }; // hash_map<X,Y> <-> python dict object template <class ToExport> void fromdict(ToExport *m, boost::python::dict d) { typedef typename associative_trait<ToExport>::key_type key_type; typedef typename associative_trait<ToExport>::data_type data_type; boost::python::list values = d.values(); boost::python::list keys = d.keys(); int l = extract<int>(keys.attr("__len__")()); key_type k; data_type c; for(int i = 0 ; i < l ; i++) { k = extract<key_type>(keys[i]); c = extract<data_type>(values[i]); (*m)[k] = c; } } template <class ToExport> typename associative_trait<ToExport>::size_type dict_len(ToExport* d) { return d->size(); } template <class ToExport> typename associative_trait<ToExport>::data_type dict_getItem(ToExport* d, const typename associative_trait<ToExport>::key_type& key) { typename associative_trait<ToExport>::iterator it; it = d->find(key); if(it != d->end()) { return it->second; } PythonExc_KeyError err; err.error_str = "key not in dict"; throw err; } template <class ToExport> void dict_setItem(ToExport* d, const typename associative_trait<ToExport>::key_type& key, const typename associative_trait<ToExport>::data_type& data) { (*d)[key] = data; } template <class ToExport> void dict_delItem(ToExport *d, const typename associative_trait<ToExport>::key_type& key) { typename associative_trait<ToExport>::size_type count; count = d->erase(key); if(count == 0) { PythonExc_KeyError err; err.error_str = "key not in dict"; throw err; } } template <class ToExport> void dict_clear(ToExport *d) { d->clear(); } template <class ToExport> ToExport dict_copy(ToExport *d) { return ToExport(*d); } template <class ToExport> bool dict_has_key(ToExport *d, const typename associative_trait<ToExport>::key_type& key) { return d->find(key) != d->end(); } template <class ToExport> boost::python::list dict_items(ToExport *d) { boost::python::list result; typename associative_trait<ToExport>::iterator it; for(it = d->begin() ; it != d->end() ; ++it) { result.append(boost::python::make_tuple(it->first, it->second)); } return result; } template <class ToExport> boost::python::list dict_keys(ToExport *d) { boost::python::list result; typename associative_trait<ToExport>::iterator it; for(it = d->begin() ; it != d->end() ; ++it) { result.append(it->first); } return result; } template <class ToExport> boost::python::list dict_values(ToExport *d) { boost::python::list result; typename associative_trait<ToExport>::iterator it; for(it = d->begin() ; it != d->end() ; ++it) { result.append(it->second); } return result; } template <class ToExport> void dict_update(ToExport *d, ToExport *d1) { typename associative_trait<ToExport>::iterator it; for(it = d1->begin() ; it != d1->end() ; ++it) { (*d)[it->first] = it->second; } } template <class ToExport> typename associative_trait<ToExport>::data_type dict_setdefault(ToExport *d, const typename associative_trait<ToExport>::key_type& key, const typename associative_trait<ToExport>::data_type& def) { typename associative_trait<ToExport>::iterator it; it = d->find(key); if(it != d->end()) return it->second; (*d)[key] = def; return def; } template <class ToExport> typename associative_trait<ToExport>::data_type dict_setdefault_def(ToExport *d, const typename associative_trait<ToExport>::key_type& key) { typedef typename associative_trait<ToExport>::data_type data_type; return dict_setdefault(d, key, data_type()); } template <class ToExport> boost::python::object dict_get(ToExport *d, const typename associative_trait<ToExport>::key_type& key, boost::python::object def) { typename associative_trait<ToExport>::iterator it; it = d->find(key); if(it != d->end()) return object(it->second); return def; } template <class ToExport> boost::python::object dict_get_def(ToExport *d, const typename associative_trait<ToExport>::key_type& key) { return dict_get(d, key, object()); } template <class ToExport> boost::python::tuple dict_popitem(ToExport *d) { if(d->empty()) { PythonExc_KeyError err; err.error_str = "popitem(): dictionnary is empty"; throw err; } typename associative_trait<ToExport>::value_type value = *d->begin(); d->erase(d->begin()); return boost::python::make_tuple(value.first, value.second); } template <class ToExport> class dict_Iterator { public: typedef typename associative_trait<ToExport>::iterator iterator; typedef typename associative_trait<ToExport>::value_type value_type; dict_Iterator() {} dict_Iterator(const dict_Iterator& i) : it(i.it), end(i.end) { } dict_Iterator(ToExport *d) { it = d->begin(); end = d->end(); } protected: iterator it, end; }; template <class ToExport> class dict_ItemsIterator : public dict_Iterator<ToExport> { public: typedef typename associative_trait<ToExport>::iterator iterator; typedef typename associative_trait<ToExport>::value_type value_type; dict_ItemsIterator() : dict_Iterator<ToExport>() {} dict_ItemsIterator(const dict_ItemsIterator& i) : dict_Iterator<ToExport>(i) {} dict_ItemsIterator(ToExport *d) : dict_Iterator<ToExport>(d) {} boost::python::tuple next() { if(it == end) { throw PythonExc_StopIteration(); } boost::python::tuple t = boost::python::make_tuple(it->first, it->second); ++it; return t; } dict_ItemsIterator copy() const { return dict_ItemsIterator(*this); } }; template <class ToExport> dict_ItemsIterator<ToExport> dict_iteritems(ToExport *d) { return dict_ItemsIterator<ToExport>(d); } template <class ToExport> class dict_KeysIterator : public dict_Iterator<ToExport> { public: typedef typename associative_trait<ToExport>::iterator iterator; typedef typename associative_trait<ToExport>::key_type key_type; dict_KeysIterator() : dict_Iterator<ToExport>() {} dict_KeysIterator(const dict_KeysIterator& i) : dict_Iterator<ToExport>(i) {} dict_KeysIterator(ToExport *d) : dict_Iterator<ToExport>(d) {} key_type next() { if(it == end) { throw PythonExc_StopIteration(); } key_type key = it->first; ++it; return key; } dict_KeysIterator copy() const { return dict_KeysIterator(*this); } }; template <class ToExport> dict_KeysIterator<ToExport> dict_iterkeys(ToExport *d) { return dict_KeysIterator<ToExport>(d); } template <class ToExport> class dict_ValuesIterator : public dict_Iterator<ToExport> { public: typedef typename associative_trait<ToExport>::iterator iterator; typedef typename associative_trait<ToExport>::data_type data_type; dict_ValuesIterator() : dict_Iterator<ToExport>() {} dict_ValuesIterator(const dict_ValuesIterator& i) : dict_Iterator<ToExport>(i) {} dict_ValuesIterator(ToExport *d) : dict_Iterator<ToExport>(d) {} data_type next() { if(it == end) { throw PythonExc_StopIteration(); } data_type data = it->second; ++it; return data; } dict_ValuesIterator copy() const { return dict_ValuesIterator(*this); } }; template <class ToExport> dict_ValuesIterator<ToExport> dict_itervalues(ToExport *d) { return dict_ValuesIterator<ToExport>(d); } template <class ToExport> std::string dict_print(ToExport *d) { typename associative_trait<ToExport>::iterator it; stringstream ss; ss << "{"; for(it = d->begin() ; it != d->end() ; it++) { ss << " (" << it->first << ": " << it->second << ")"; } ss << " }"; return ss.str(); } template<class ToExport, class Init> class_<ToExport> dict_(const char *name, const char* doc, Init ini) { class_<dict_ItemsIterator<ToExport> >("dictItemsIterator", init<optional<ToExport*> >()) .def("__iter__", &dict_ItemsIterator<ToExport>::copy) .def("next", &dict_ItemsIterator<ToExport>::next) ; class_<dict_ValuesIterator<ToExport> >("dictValuesIterator", init<optional<ToExport*> >()) .def("__iter__", &dict_ValuesIterator<ToExport>::copy) .def("next", &dict_ValuesIterator<ToExport>::next) ; class_<dict_KeysIterator<ToExport> >("dictKeysIterator", init<optional<ToExport*> >()) .def("__iter__", &dict_KeysIterator<ToExport>::copy) .def("next", &dict_KeysIterator<ToExport>::next) ; return class_<ToExport>(name, doc, ini) .def("__len__", dict_len<ToExport>) .def("__getitem__", dict_getItem<ToExport>) .def("__setitem__", dict_setItem<ToExport>) .def("__delitem__", dict_delItem<ToExport>) .def("clear", dict_clear<ToExport>) .def("copy", dict_copy<ToExport>) .def("has_key", dict_has_key<ToExport>) .def("__contains__", dict_has_key<ToExport>) .def("items", dict_items<ToExport>) .def("keys", dict_keys<ToExport>) .def("values", dict_values<ToExport>) .def("update", dict_update<ToExport>) .def("get", dict_get<ToExport>) .def("get", dict_get_def<ToExport>) .def("setdefault", dict_setdefault<ToExport>) .def("setdefault", dict_setdefault_def<ToExport>) .def("popitem", dict_popitem<ToExport>) .def("iteritems", dict_iteritems<ToExport>) .def("iterkeys", dict_iterkeys<ToExport>) .def("itervalues", dict_itervalues<ToExport>) .def("__str__", dict_print<ToExport>) .def("__repr__", dict_print<ToExport>) .def("__iter__", dict_iteritems<ToExport>) .def("fromdict", fromdict<ToExport>) ; } template <class ToExport, class Init> class_<ToExport> dict_(const char* name, Init ini) { return dict_<ToExport>(name, "", ini); } #endif /*************************************************************************** stl2list.wcc - description ------------------- copyright : (C) 2003 by Pierre Barbier de Reuille email : pierre.barbier@cirad.fr ***************************************************************************/ /*************************************************************************** * * GNU General Public Licence * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ #ifndef _STL2LIST_WCC_ #define _STL2LIST_WCC_ #include <ext/hash_set> #include <ext/slist> #include <vector> #include <algorithm> #include <iostream> #include <iterator> #include <list> #include <set> using namespace std; using namespace __gnu_cxx; #include "exception.hh" // -> list template <class ForwardIterator> boost::python::list ToList(ForwardIterator first, ForwardIterator last) { boost::python::list l; ForwardIterator it; for(it = first ; it != last ; ++it) { l.append(*it); } return l; } template <class ToExport> boost::python::list python_tolist(ToExport *l) { return ToList(l->begin(), l->end()); } /*********************************** * * Notations: * * - X : container type * - a,b : container instance * - T : container value type * - u,v : container value instance * - I : container iterator type * - i,j : container iterator instance * - os : ostream instance * * The semantic of the expressions is to be found in the STL ... * * Valid expressions for generic container : * * - container_trait<X> * - iterator_trait<container_trait<X>::iterator> * - a.begin() * - a.end() * - insert_iterator<X> ii( a, i ) * - extract<T>( u ) // Need boost python export * - a.erase( i ) * - a.size() * - i++ * - u = *i * - copy( i, j, ouput_iterator ) * - count( i, j, u ) * - find( i, j, u ) * - a.erase( i, j ) * - a.erase( i ) * - hash<X>(a) * - equal_to<X>()( a,b ) * - not_equal_to<X>()( a,b ) * - greater_equal<X>()( a,b ) * - less_equal<X>()( a,b ) * - greater<X>()( a,b ) * - less<X>()( a,b ) * - os << u * * Tag specific requirements : * * * Iterator tag, requirement other than the one defined in the STL * iterator_traits<container_trait<X>::iterator>::iterator_category : * * * if not random_access_iterator_tag: * - a.sort() * * if not forward_iterator_tag: * - advance( i, n ) // n can be negative * - --i * * * sorted tag * * unsorted_container_tag: * * if forward_iterator_tag: * - a.reverse() * * else * - reverse( i,j ) * * if not random_access_iterator_tag: * - a.sort() * - a.erase( i,j ) // returns the iterator on the element following * immediatly the erased ones * - a.insert( i, u ) // returns the iterator on the inserted element * * sorted_container_tag: * - a.insert( u ) * * * mutable tag * * mutable_container_tag: * - *i = u * ***************************/ struct unsorted_container_tag { }; struct sorted_container_tag { }; struct mutable_container_tag { }; struct immutable_container_tag { }; template<class Container> struct container_trait { typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; }; template<class _Tp> struct container_trait<slist<_Tp> > { typedef slist<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef unsorted_container_tag sorted_tag; typedef mutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<std::list<_Tp> > { typedef std::list<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef unsorted_container_tag sorted_tag; typedef mutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<vector<_Tp> > { typedef vector<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef unsorted_container_tag sorted_tag; typedef mutable_container_tag mutable_tag; }; template <> struct container_trait<bit_vector> { typedef bit_vector Container; typedef Container::value_type value_type; typedef Container::iterator iterator; typedef Container::const_iterator const_iterator; typedef Container::reference reference; typedef Container::const_reference const_reference; typedef Container::pointer pointer; typedef Container::difference_type difference_type; typedef Container::size_type size_type; typedef unsorted_container_tag sorted_tag; typedef mutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<set<_Tp> > { typedef set<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef sorted_container_tag sorted_tag; typedef immutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<hash_set<_Tp> > { typedef hash_set<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef sorted_container_tag sorted_tag; typedef immutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<multiset<_Tp> > { typedef multiset<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef sorted_container_tag sorted_tag; typedef immutable_container_tag mutable_tag; }; template<class _Tp> struct container_trait<hash_multiset<_Tp> > { typedef hash_multiset<_Tp> Container; typedef typename Container::value_type value_type; typedef typename Container::iterator iterator; typedef typename Container::const_iterator const_iterator; typedef typename Container::reference reference; typedef typename Container::const_reference const_reference; typedef typename Container::pointer pointer; typedef typename Container::difference_type difference_type; typedef typename Container::size_type size_type; typedef sorted_container_tag sorted_tag; typedef immutable_container_tag mutable_tag; }; // list -> template <class ToExport> void python_fromlist(ToExport* vec, boost::python::list l) { typedef typename container_trait<ToExport>::value_type value_type; int len = extract<int>(l.attr("__len__")()); for(int i = 0 ; i < len ; ++i) { insert_iterator<ToExport> ii(*vec, vec->end()); *ii = extract<value_type>(l.attr("__getitem__")(i)); } } template <class ToExport> typename container_trait<ToExport>::value_type list_getItem(ToExport* exp, typename container_trait<ToExport>::difference_type i) { typename container_trait<ToExport>::iterator it; it = PosInRange(exp, i); return *it; } template <class ToExport> void list_delItem(ToExport* exp, typename container_trait<ToExport>::difference_type i ) { typename container_trait<ToExport>::iterator it; it = PosInRange(exp, i); exp->erase(it); } template <class ToExport> typename container_trait<ToExport>::iterator PosInRange(ToExport *l, typename container_trait<ToExport>::difference_type i) { typename container_trait<ToExport>::difference_type size = l->size(); if((i >= size) || (i < -size)) { PythonExc_IndexError ind; ind.error_str = "assignment index out of range"; throw ind; } if(i < 0) { typename container_trait<ToExport>::difference_type size = l->size(); i += size; } typename container_trait<ToExport>::iterator it = l->begin(); advance(it, i); return it; } template <class ToExport> void list_setItem(ToExport* exp, typename container_trait<ToExport>::difference_type i, typename container_trait<ToExport>::value_type val) { typename container_trait<ToExport>::iterator it; it = PosInRange(exp, i); typename container_trait<ToExport>::mutable_tag mut_tag; typename container_trait<ToExport>::sorted_tag sort_tag; changeValue(exp, it, val, mut_tag, sort_tag); } template <class ToExport, class SortingTag> void changeValue(ToExport *, typename container_trait<ToExport>::iterator it, typename container_trait<ToExport>::value_type val, const mutable_container_tag&, const SortingTag&) { *it = val; } template <class ToExport> void changeValue(ToExport *exp, typename container_trait<ToExport>::iterator it, typename container_trait<ToExport>::value_type val, const immutable_container_tag&, const unsorted_container_tag&) { typename container_trait<ToExport>::iterator it1; it1 = exp->insert(it, val); it1++; exp->erase(it1); } template <class ToExport> void changeValue(ToExport *exp, typename container_trait<ToExport>::iterator it, typename container_trait<ToExport>::value_type val, const immutable_container_tag&, const sorted_container_tag&) { exp->erase(it); exp->insert(val); } template <class ToExport> void list_append(ToExport* l1, typename container_trait<ToExport>::value_type val) { insert_iterator<ToExport> ii(*l1, l1->end()); *ii = val; } template <class ToExport> ToExport list_Listadd(ToExport *l1, boost::python::list l2) { ToExport e; python_fromlist(&e, l2); return list_add(l1, &e); } template <class ToExport> void list_Listiadd(ToExport *l1, boost::python::list l2) { ToExport e; python_fromlist(&e, l2); list_iadd(l1, &e); } template <class ToExport> void list_Listextend(ToExport *l1, boost::python::list l2) { ToExport e; python_fromlist(&e, l2); return list_extend(l1, &e); } template <class ToExport> ToExport list_add(ToExport *l1, ToExport *l2) { ToExport result = *l1; list_extend(&result, l2); return result; } template <class ToExport> void list_iadd(ToExport *l1, ToExport *l2) { list_extend(l1, l2); } template <class ToExport> void list_extend(ToExport *l1, ToExport *l2) { insert_iterator<ToExport> ii(*l1, l1->end()); copy(l2->begin(), l2->end(), ii); } template <class ToExport> typename container_trait<ToExport>::size_type list_count(ToExport *l, typename container_trait<ToExport>::value_type val) { return count(l->begin(), l->end(), val); } template <class ToExport> typename container_trait<ToExport>::size_type list_index(ToExport* l, typename container_trait<ToExport>::value_type val) { typename container_trait<ToExport>::iterator first, result; first = l->begin(); result = find(first, l->end(), val); if(result != l->end()) return distance(first,result); else { PythonExc_ValueError ind; ind.error_str = "list.index(x): x not in list"; throw ind; } } template <class ToExport> void list_insert(ToExport *l, typename container_trait<ToExport>::difference_type i, typename container_trait<ToExport>::value_type val) { typename container_trait<ToExport>::iterator it; it = CheckedPos(l, i); insert_iterator<ToExport> ii(*l, it); *ii = val; } template <class ToExport, class IteratorTag> typename container_trait<ToExport>::iterator CheckedPos_tag(ToExport *l, typename container_trait<ToExport>::difference_type i, const IteratorTag&) { typename container_trait<ToExport>::iterator it = l->begin(); advance(it, i); return it; } template <class ToExport> typename container_trait<ToExport>::iterator CheckedPos_tag(ToExport *l, typename container_trait<ToExport>::difference_type i, const forward_iterator_tag&) { typename container_trait<ToExport>::iterator it = l->begin(); typename container_trait<ToExport>::difference_type size = l->size(); if(i < 0) { i = size - i; } advance(it, i); return it; } template <class ToExport> typename container_trait<ToExport>::iterator CheckedPos(ToExport *l, typename container_trait<ToExport>::difference_type i) { typename container_trait<ToExport>::difference_type size = l->size(); if(i >= size) { return l->end(); } if(i <= (-size+1)) { return l->begin(); } typename iterator_traits<typename container_trait<ToExport>::iterator>::iterator_category tag; return CheckedPos_tag(l, i, tag); } template <class ToExport> typename container_trait<ToExport>::value_type list_pop(ToExport *l) { typename iterator_traits<typename container_trait<ToExport>::iterator>::iterator_category tag; return list_pop_tag(l, tag); } template <class ToExport, class IteratorTag> typename container_trait<ToExport>::value_type list_pop_tag(ToExport *l, const IteratorTag&) { typename container_trait<ToExport>::value_type val; val = *(--l->end()); l->erase(--l->end()); return val; } template <class ToExport> typename container_trait<ToExport>::value_type list_pop_tag(ToExport *l, const forward_iterator_tag&) { typename container_trait<ToExport>::value_type val; typename container_trait<ToExport>::iterator it = l->begin(); advance(it, l->size()-1); val = *it; l->erase(it); return val; } template <class ToExport> void list_reverse(ToExport *l) { typename container_trait<ToExport>::sorted_tag tag; typename iterator_traits<typename container_trait<ToExport>::iterator>::iterator_category it_tag; list_reverse_tag(l, tag, it_tag); } template <class ToExport, class IteratorTag> void list_reverse_tag(ToExport *, const sorted_container_tag&, const IteratorTag&) { } template <class ToExport, class IteratorTag> void list_reverse_tag(ToExport *l, const unsorted_container_tag&, const IteratorTag&) { reverse(l->begin(), l->end()); } template <class ToExport> void list_reverse_tag(ToExport *l, const unsorted_container_tag&, const forward_iterator_tag&) { l->reverse(); } template <class ToExport> void list_sort(ToExport *l) { typename container_trait<ToExport>::sorted_tag tag; typename iterator_traits<typename container_trait<ToExport>::iterator>::iterator_category it_tag; list_sort_tag(l, tag, it_tag); } template <class ToExport, class IteratorTag> void list_sort_tag(ToExport *, const sorted_container_tag&, const IteratorTag&) { } template <class ToExport, class IteratorTag> void list_sort_tag(ToExport *l, const unsorted_container_tag&, const IteratorTag&) { l->sort(); } template <class ToExport> void list_sort_tag(ToExport *l, const unsorted_container_tag&, const random_access_iterator_tag&) { sort(l->begin(), l->end()); } template <class ToExport> bool list_contains(ToExport *l, typename container_trait<ToExport>::value_type val) { return find(l->begin(), l->end(), val) != l->end(); } template <class ToExport> ToExport list_getSlice(ToExport *l, typename container_trait<ToExport>::size_type i1, typename container_trait<ToExport>::size_type i2) { ToExport e; if(i1 >= i2) { return e; } insert_iterator<ToExport> ii(e,e.end()); typename container_trait<ToExport>::iterator first, last; first = CheckedPosIterator(l, i1); last = CheckedPosIterator(l, i2); copy(first, last, ii); return e; } template <class ToExport> void list_setListSlice(ToExport *l, typename container_trait<ToExport>::size_type i1, typename container_trait<ToExport>::size_type i2, boost::python::list l2) { ToExport e; python_fromlist(&e, l2); list_setSlice(l, i1, i2, &e); } template <class ToExport> void list_setSlice(ToExport *l, typename container_trait<ToExport>::size_type i1, typename container_trait<ToExport>::size_type i2, ToExport *l2) { typename container_trait<ToExport>::iterator first, last, insert_pt; if(i1 >= i2) { return; } first = CheckedPosIterator(l, i1); last = CheckedPosIterator(l, i2); insert_pt = erase_elements(l, first, last); insert_iterator<ToExport> ii(*l, insert_pt); copy(l2->begin(), l2->end(), ii); } template <class ToExport> typename container_trait<ToExport>::iterator CheckedPosIterator(ToExport *l, typename container_trait<ToExport>::size_type inc) { typename container_trait<ToExport>::size_type size = l->size(); if(inc >= size) return l->end(); else if(inc == 0) return l->begin(); typename container_trait<ToExport>::iterator it = l->begin(); advance(it, inc); return it; } template <class ToExport> void list_delSlice(ToExport *l, typename container_trait<ToExport>::size_type i1, typename container_trait<ToExport>::size_type i2) { typename container_trait<ToExport>::iterator first, last; if(i1 >= i2) { return; } first = CheckedPosIterator(l, i1); last = CheckedPosIterator(l, i2); erase_elements(l, first, last); } template <class ToExport> typename container_trait<ToExport>::iterator erase_elements(ToExport *l, typename container_trait<ToExport>::iterator first, typename container_trait<ToExport>::iterator last) { typename container_trait<ToExport>::sorted_tag tag; return erase_elements(l,first,last,tag); } template <class ToExport> typename container_trait<ToExport>::iterator erase_elements(ToExport *l, typename container_trait<ToExport>::iterator first, typename container_trait<ToExport>::iterator last, const unsorted_container_tag&) { return l->erase(first, last); } template <class ToExport> typename container_trait<ToExport>::iterator erase_elements(ToExport *l, typename container_trait<ToExport>::iterator first, typename container_trait<ToExport>::iterator last, const sorted_container_tag&) { l->erase(first, last); return l->end(); } template <class ToExport> typename container_trait<ToExport>::size_type list_len(ToExport* l) { return l->size(); } template <class ToExport> void list_remove(ToExport *l, typename container_trait<ToExport>::value_type val) { typename container_trait<ToExport>::iterator it; it = find(l->begin(), l->end(), val); if(it == l->end()) { PythonExc_ValueError ind; ind.error_str = "list.remove(x): x not in list"; throw ind; } l->erase(it); } template <class ToExport> ToExport list_duplicate(ToExport *l, int times) { if(times < 1) { return ToExport(); } else { ToExport nl; insert_iterator<ToExport> ii(nl, nl.end()); for(int i = 0 ; i < times ; ++i) { copy(l->begin(), l->end(), ii); } return nl; } } namespace __gnu_cxx { template <class Content> struct hash<vector<Content> > { int operator()(const vector<Content>& l) const { return l.size(); } }; template <> struct hash<bit_vector> { int operator()(const bit_vector& l) const { return l.size(); } }; template <class Content> struct hash<hash_set<Content> > { int operator()(const hash_set<Content>& l) const { return l.size(); } }; template <class Content> struct hash<multiset<Content> > { int operator()(const multiset<Content>& l) const { return l.size(); } }; template <class Content> struct hash<hash_multiset<Content> > { int operator()(const hash_multiset<Content>& l) const { return l.size(); } }; template <class Content> struct hash<set<Content> > { int operator()(const set<Content>& l) const { return l.size(); } }; template <class Content> struct hash<slist<Content> > { int operator()(const slist<Content>& l) const { return l.size(); } }; template <class Content> struct hash<std::list<Content> > { int operator()(const std::list<Content>& l) const { return l.size(); } }; template <> struct hash<std::string> { int operator()(const std::string& s) const { return op(s.c_str()); } hash<const char*> op; }; template <class InputIterator> bool CompareGreaterIt(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, size_t s1, size_t s2) { pair<InputIterator,InputIterator> result; InputIterator it1,it2; if(s1 < s2) { result = mismatch(first1, last1, first2); it1 = result.first; it2 = result.second; if(it1 == last1) { return false; } } else { result = mismatch(first2, last2, first1); it2 = result.first; it1 = result.second; if(it2 == last2) { return true; } } return *it1 > *it2; } template <class InputIterator> bool CompareLessIt(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2, size_t s1, size_t s2) { pair<InputIterator,InputIterator> result; InputIterator it1,it2; if(s2 < s1) { result = mismatch(first2, last2, first1); it2 = result.first; it1 = result.second; if(it2 == last2) { return false; } } else { result = mismatch(first1, last1, first2); it1 = result.first; it2 = result.second; if(it1 == last1) { return true; } } return *it1 < *it2; } template <class Content> bool operator>(const hash_multiset<Content>& e1, const hash_multiset<Content>& e2) { return CompareGreaterIt(e1.begin(), e1.end(), e2.begin(), e2.end(), e1.size(), e2.size()); } template <class Content> bool operator<(const hash_set<Content>& e1, const hash_set<Content>& e2) { return CompareLessIt(e1.begin(), e1.end(), e2.begin(), e2.end(), e1.size(), e2.size()); } template <class Content> bool operator<(const hash_multiset<Content>& e1, const hash_multiset<Content>& e2) { return CompareLessIt(e1.begin(), e1.end(), e2.begin(), e2.end(), e1.size(), e2.size()); } template <class Content> bool operator>(const hash_set<Content>& e1, const hash_set<Content>& e2) { return CompareGreaterIt(e1.begin(), e1.end(), e2.begin(), e2.end(), e1.size(), e2.size()); } template <class Content> bool operator<=(const hash_multiset<Content>& e1, const hash_multiset<Content>& e2) { return !(e1>e2); } template <class Content> bool operator<=(const hash_set<Content>& e1, const hash_set<Content>& e2) { return !(e1>e2); } template <class Content> bool operator>=(const hash_multiset<Content>& e1, const hash_multiset<Content>& e2) { return !(e1<e2); } template <class Content> bool operator>=(const hash_set<Content>& e1, const hash_set<Content>& e2) { return !(e1<e2); } } template <class ToExport> int python_hash(const ToExport& e) { return hash<ToExport>()(e); } template <class ToExport> bool python_equal_to(const ToExport& e1, const ToExport& e2) { return equal_to<ToExport>()(e1,e2); } template <class ToExport> bool python_not_equal_to(const ToExport& e1, const ToExport& e2) { return not_equal_to<ToExport>()(e1,e2); } template <class ToExport> bool python_greater_equal(const ToExport& e1, const ToExport& e2) { return greater_equal<ToExport>()(e1,e2); } template <class ToExport> bool python_less_equal(const ToExport& e1, const ToExport& e2) { return less_equal<ToExport>()(e1,e2); } template <class ToExport> bool python_greater(const ToExport& e1, const ToExport& e2) { return greater<ToExport>()(e1,e2); } template <class ToExport> bool python_less(const ToExport& e1, const ToExport& e2) { return less<ToExport>()(e1,e2); } template <class ToExport> std::string list_print(const ToExport& l) { stringstream s; typename container_trait<ToExport>::const_iterator it; s << "{"; for(it = l.begin() ; it != l.end() ; ++it) { s << " " << *it; } s << " }"; return s.str(); } template<class ToExport, class Init> class_<ToExport> list_(const char *name, const char* doc, Init init) { return class_<ToExport>(name, doc, init) .def("__getitem__", list_getItem<ToExport>) .def("__setitem__", list_setItem<ToExport>) .def("__delitem__", list_delItem<ToExport>) .def("append", list_append<ToExport>) .def("extend", list_extend<ToExport>) .def("extend", list_Listextend<ToExport>) .def("count", list_count<ToExport>) .def("index", list_index<ToExport>) .def("insert", list_insert<ToExport>) .def("pop", list_pop<ToExport>) .def("remove", list_remove<ToExport>) .def("reverse", list_reverse<ToExport>) .def("sort", list_sort<ToExport>) .def("__eq__", python_equal_to<ToExport>) .def("__ne__", python_not_equal_to<ToExport>) .def("__contains__", list_contains<ToExport>) .def("__ge__", python_greater_equal<ToExport>) .def("__gt__", python_greater<ToExport>) .def("__le__", python_less_equal<ToExport>) .def("__lt__", python_less<ToExport>) .def("__getslice__", list_getSlice<ToExport>) .def("__setslice__", list_setSlice<ToExport>) .def("__setslice__", list_setListSlice<ToExport>) .def("__delslice__", list_delSlice<ToExport>) .def("__hash__", python_hash<ToExport>) .def("__add__", list_add<ToExport>) .def("__add__", list_Listadd<ToExport>) .def("__iadd__", list_iadd<ToExport>) .def("__iadd__", list_Listiadd<ToExport>) .def("__imul__", list_duplicate<ToExport>) .def("__mul__", list_duplicate<ToExport>) .def("__len__", list_len<ToExport>) .def("__str__", list_print<ToExport>) .def("__repr__", list_print<ToExport>) .def("__iter__", boost::python::iterator<ToExport>()) .def("tolist", python_tolist<ToExport>) .def("fromlist", python_fromlist<ToExport>) ; } template<class ToExport, class Init> class_<ToExport> list_(const char *name, Init init) { return list_<ToExport>(name, "", init); } #endif /*************************************************************************** exception.wcc - description ------------------- copyright : (C) 2003 by Pierre Barbier de Reuille email : pierre.barbier@cirad.fr ***************************************************************************/ /*************************************************************************** * * GNU General Public Licence * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS For A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ #include "exception.hh" void index_trans(const PythonExc_IndexError& err) { PyErr_SetString(PyExc_IndexError, err.error_str); } void value_trans(const PythonExc_ValueError& err) { PyErr_SetString(PyExc_ValueError, err.error_str); } void key_trans(const PythonExc_KeyError& err) { PyErr_SetString(PyExc_KeyError, err.error_str); } void stopiteration_trans(const PythonExc_StopIteration& err) { PyErr_SetString(PyExc_StopIteration, err.error_str); } void define_stl_exceptions() { register_exception_translator<PythonExc_IndexError>(&index_trans); register_exception_translator<PythonExc_ValueError>(&value_trans); register_exception_translator<PythonExc_KeyError>(&key_trans); register_exception_translator<PythonExc_StopIteration>(&stopiteration_trans); }
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
You can post them here. After we discuss and get comfortable with your approach, the first things I'll probably ask you for are tests for the Boost.Python test suite and HTML documentation pages.
Regards,
Sorry for the delay but I was on vacation ... I begin by sending the three files used to export STL containers.
Hmm, Joel just checked in some support for this. See http://tinyurl.com/i9gv.
By the time, it only works with g++-3.2 or later, but it's just a question of namespace and include locations. There is a _small_ help at the beginning. The only thing not written is for the handling of the exceptions: you have to call define_stl_exceptions() in your module function. The wcc files correspond to your hpp ones and the hh is here for tiled compilation only.
The first thing I'd need in order to evaluate this is some examples and documentation which describe what it does.
My main concern about what you said is about the Boost.Python test suite ... how to document myself about how it works ?
I can't understand what you mean. Can you rephrase? Testing and documentation are two separate things; I want tests for libs/python/test and documentation for libs/python/doc. Oh, and BTW, the GPL is not Boost-compatible. http://www.boost.org/more/lib_guide.htm#License -- Dave Abrahams Boost Consulting www.boost-consulting.com
David Abrahams wrote:
Hmm, Joel just checked in some support for this. See http://tinyurl.com/i9gv.
I didn't know this project. My goal, even if close, is somehow different: I want to be able to use the STL containers as if there were python list. At best, anybody should be able to export its own container as a python list. But it could be a good idea to use what Joel did ...
By the time, it only works with g++-3.2 or later, but it's just a question of namespace and include locations. There is a _small_ help at the beginning. The only thing not written is for the handling of the exceptions: you have to call define_stl_exceptions() in your module function. The wcc files correspond to your hpp ones and the hh is here for tiled compilation only.
The first thing I'd need in order to evaluate this is some examples and documentation which describe what it does.
Ok, I join an example of module along with a python test file. You just need to execute ths python file to test ... For the documentation I'm writing it and I'll send it to you as soon as possible.
My main concern about what you said is about the Boost.Python test suite ... how to document myself about how it works ?
I can't understand what you mean. Can you rephrase? Testing and documentation are two separate things; I want tests for libs/python/test and documentation for libs/python/doc.
I just wondered if you had any rule to write test suite. But if the kind of test I send you with this mail is ok ...
Oh, and BTW, the GPL is not Boost-compatible. http://www.boost.org/more/lib_guide.htm#License
Oh ... I didn't notice that ! By the way, what is the licence of Boost.Python ? I don't see any licence ! I think the best is to include my work (if you do include it) with the same licence as Boost.Python. Thanks, PS : I just noticed an error ... so I resend the stl2list.wcc file ... I can't assure it's totally unbugged -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
David Abrahams wrote:
Hmm, Joel just checked in some support for this. See http://tinyurl.com/i9gv.
I didn't know this project. My goal, even if close, is somehow different: I want to be able to use the STL containers as if there were python list.
How is that different from what Joel did?
At best, anybody should be able to export its own container as a python list. But it could be a good idea to use what Joel did ...
What you did does not appear to export the container "as a python list", but as a Python sequence. Exporting "as a list" would be more along the lines of the custom rvalue converters described in http://www.boost.org/libs/python/doc/v2/faq.html#question2, I think.
By the time, it only works with g++-3.2 or later, but it's just a question of namespace and include locations. There is a _small_ help at the beginning. The only thing not written is for the handling of the exceptions: you have to call define_stl_exceptions() in your module function. The wcc files correspond to your hpp ones and the hh is here for tiled compilation only.
The first thing I'd need in order to evaluate this is some examples and documentation which describe what it does.
Ok, I join an example of module along with a python test file. You just need to execute ths python file to test ... For the documentation I'm writing it and I'll send it to you as soon as possible.
My main concern about what you said is about the Boost.Python test suite ... how to document myself about how it works ?
I can't understand what you mean. Can you rephrase? Testing and documentation are two separate things; I want tests for libs/python/test and documentation for libs/python/doc.
I just wondered if you had any rule to write test suite. But if the kind of test I send you with this mail is ok ...
Actually, I would strongly prefer a test using the same format as all of the other tests, with doctest or using the unittest module as polymorphism.py does.
Oh, and BTW, the GPL is not Boost-compatible. http://www.boost.org/more/lib_guide.htm#License
Oh ... I didn't notice that ! By the way, what is the licence of Boost.Python ? I don't see any licence !
Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. -- Dave Abrahams Boost Consulting www.boost-consulting.com
David Abrahams wrote:
How is that different from what Joel did?
Joel "just" did the hardest part ... what's missing are methods like append, extend, sort, revert ... By the way, I cannot successfully compile his example and it only handle the vector container. (But it's better than what I did, mainly with his reference thing that allows you to delete the object without having dangling pointers and still permits to modify the list using the __getitem__ method, and probably because he seems to use a method more "boost-like") Then, there is also the exportation of mapping objects with the same behaviour as dict objects.
At best, anybody should be able to export its own container as a python list. But it could be a good idea to use what Joel did ...
What you did does not appear to export the container "as a python list", but as a Python sequence. Exporting "as a list" would be more along the lines of the custom rvalue converters described in http://www.boost.org/libs/python/doc/v2/faq.html#question2, I think.
You're right, but a more correct assertion would be that I want to export STL container so that they behave as close as possible to python lists.
Actually, I would strongly prefer a test using the same format as all of the other tests, with doctest or using the unittest module as polymorphism.py does.
Ok, that was what I wanted to know :o) -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77 fax : (33) 4 67 61 56 68
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
David Abrahams wrote:
How is that different from what Joel did?
Joel "just" did the hardest part ... what's missing are methods like append, extend, sort, revert ... By the way, I cannot successfully compile his example and it only handle the vector container. (But it's better than what I did, mainly with his reference thing that allows you to delete the object without having dangling pointers and still permits to modify the list using the __getitem__ method, and probably because he seems to use a method more "boost-like") Then, there is also the exportation of mapping objects with the same behaviour as dict objects.
OK; if you could find a way to integrate with Joel's work, it would be great. Perhaps the two of you could discuss the design and come up with something?
At best, anybody should be able to export its own container as a python list. But it could be a good idea to use what Joel did ...
What you did does not appear to export the container "as a python list", but as a Python sequence. Exporting "as a list" would be more along the lines of the custom rvalue converters described in http://www.boost.org/libs/python/doc/v2/faq.html#question2, I think.
You're right, but a more correct assertion would be that I want to export STL container so that they behave as close as possible to python lists.
Yeah; since Guido refuses to define "sequence" I guess what I said was meaningless ;-> -- Dave Abrahams Boost Consulting www.boost-consulting.com
Pierre Barbier de Reuille <pierre.barbier@cirad.fr> writes:
David Abrahams wrote:
Hmm, Joel just checked in some support for this. See http://tinyurl.com/i9gv.
I didn't know this project. My goal, even if close, is somehow different: I want to be able to use the STL containers as if there were python list.
How is that different from what Joel did?
At best, anybody should be able to export its own container as a python list. But it could be a good idea to use what Joel did ...
What you did does not appear to export the container "as a python list", but as a Python sequence. Exporting "as a list" would be more along the lines of the custom rvalue converters described in http://www.boost.org/libs/python/doc/v2/faq.html#question2, I think.
By the time, it only works with g++-3.2 or later, but it's just a question of namespace and include locations. There is a _small_ help at the beginning. The only thing not written is for the handling of the exceptions: you have to call define_stl_exceptions() in your module function. The wcc files correspond to your hpp ones and the hh is here for tiled compilation only.
The first thing I'd need in order to evaluate this is some examples and documentation which describe what it does.
Ok, I join an example of module along with a python test file. You just need to execute ths python file to test ... For the documentation I'm writing it and I'll send it to you as soon as possible.
My main concern about what you said is about the Boost.Python test suite ... how to document myself about how it works ?
I can't understand what you mean. Can you rephrase? Testing and documentation are two separate things; I want tests for libs/python/test and documentation for libs/python/doc.
I just wondered if you had any rule to write test suite. But if the kind of test I send you with this mail is ok ...
Actually, I would strongly prefer a test using the same format as all of the other tests, with doctest or using the unittest module as polymorphism.py does.
Oh, and BTW, the GPL is not Boost-compatible. http://www.boost.org/more/lib_guide.htm#License
Oh ... I didn't notice that ! By the way, what is the licence of Boost.Python ? I don't see any licence !
Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (2)
-
David Abrahams -
Pierre Barbier de Reuille