[C++-sig] Wrapping std::map using Boost::Python

James Knight neworderofjamie at gmail.com
Wed May 9 13:23:36 CEST 2007


Hi,

I'm trying to wrap std::map using boost::python so my embedded python code
can access maps.  I have the following wrapper class:

//Map - takes e.g std::map<std::string,thing*> as MapType
template<class MapType>
struct MapItem
{
    //Typedefine the key and value types for ease
    typedef typename MapType::key_type KeyType;
    typedef typename MapType::mapped_type ValueType;

    static ValueType& Get(MapType & x,KeyType const& i)
    {
        if( x.find(i) != x.end() )
            return x[i];
        //Some kind of error!
    }
    static void Set(MapType & x,KeyType const& i,ValueType const& v)
    {
        x[i]=v; // use map autocreation feature
    }
    static void Del(MapType & x,KeyType const& i)
    {
        if( x.find(i) != x.end() )
            x.erase(i);

    }
}

And the following Boost::Python class definition to wrap a particular map:

[source lang="cpp"]
boost::python::class_<std::map<std::string,SubGrid> >("SubGridMap")
    .def("__len__",&std::map<std::string,SubGrid>::size)
    .def("clear",&std::map<std::string,SubGrid>::clear)
    .def("__getitem__",&MapItem<std::map<std::string,SubGrid>
>::Get,boost::python::return_value_policy<boost::python::copy_non_const_reference>())
    .def("__setitem__",&MapItem<std::map<std::string,SubGrid>
>::Set,boost::python::with_custodian_and_ward<1,2>()) // to let container
keep value
    .def("__delitem__",&MapItem<std::map<std::string,SubGrid> >::Del)
;

I really need iterator support and following the Python Wiki entry on STL
containers, have written a function like this to convert the std::map to a
std::list of tuples as boost::python::iterator doesn't seem to be compatible
with std::map (which seems a bit icky but makes sense):

static std::list<boost::tuple<KeyType,ValueType> > Items(MapType const& x)
{
    std::list<boost::tuple<KeyType,ValueType> > t;
    typename MapType::const_iterator it;

    for(it=x.begin(); it!=x.end(); ++it)
        t.push_back(boost::make_tuple(it->first,it->second));

    return t;
}


But the wiki entry irritatingly stops short of telling you how the hell you
wrap it into an __iter__ and the attachement to the wiki entry seems to be
empty...Has anyone done this or have any ideas?

Cheers

Jamie
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20070509/de04026c/attachment.htm>


More information about the Cplusplus-sig mailing list