In this post there are code listings for std::map wraper to python. All files can be easily downloaded from https://sites.google.com/site/ppiotrowblog/home/files file: map.zip.
First listing is for code, which converts boost::python::dict into std::map.
#include <map>
#include <boost/python.hpp>
#include <string>
#ifndef MAPHOLDER_HPP
#define MAPHOLDER_HPP
typedef std::map<std::string,std::string> StringMap;
class MapHolder{
public:
/*Constructors*/
MapHolder();
MapHolder(boost::python::dict& py_dict);
/*Modifiers*/
void update_map(boost::python::dict& py_dict);
void clear();
boost::python::dict get_dict();
size_t size();
protected:
StringMap map_;
};
#endif
It allows to create empty map or map with values from python dict. It also allows to clear map or add some elements with update_map method.
Here comes methods implementation
#include "MapHolder.hpp"
#include <iostream>
MapHolder::MapHolder(){
};
MapHolder::MapHolder(boost::python::dict& py_dict){
update_map(py_dict);
}
void MapHolder::update_map(boost::python::dict& py_dict){
boost::python::list keys = py_dict.keys();
for (int i = 0; i < len(keys); ++i) {
boost::python::extract<std::string> extracted_key(keys[i]);
if(!extracted_key.check()){
std::cout<<"Key invalid, map might be incomplete"<<std::endl;
continue;
}
std::string key = extracted_key;
boost::python::extract<std::string> extracted_val(py_dict[key]);
if(!extracted_val.check()){
std::cout<<"Value invalid, map might be incomplete"<<std::endl;
continue;
}
std::string value = extracted_val;
map_[key] = value;
}
}
boost::python::dict MapHolder::get_dict(){
boost::python::dict py_dict;
for(StringMap::const_iterator it = map_.begin(); it != map_.end(); ++it)
py_dict[it->first]=it->second;
return py_dict;
}
void MapHolder::clear(){
map_.clear();
}
After implementation lets expose that in Python.
#include <algorithm>
#include <boost/python.hpp>
#include "MapHolder.hpp"
#include "FooTicTacToe.hpp"
BOOST_PYTHON_MODULE(cpp_collections)
{
using namespace boost::python;
class_<MapHolder> ("map", init<>())
.def(init<boost::python::dict&>())
.def("update_map", &MapHolder::update_map)
.def("clear", &MapHolder::clear)
.def("size", &MapHolder::size)
.def("to_dict",&MapHolder::get_dict);
class_<FooTicTacToe, bases<MapHolder> >("FooTicTacToe", init<>())
.def(init<boost::python::dict&>())
.def("is_winner", &FooTicTacToe::FooIsWinner);
}
At this moment ignore FooTicTacToe class.
Compile module with sconstruct file
# Przemek -*- mode: Python; -*-
##Linux Parameters
boost_path='/usr/include/boost/'
python_path='/usr/include/python2.7/'
##End
import platform, os
boost_libs=['boost_python']
env = Environment()
if(platform.system() == "Linux"):
env.Append(CPPPATH=[boost_path,python_path])
#modul pythona
env.SharedLibrary(target='cpp_collections.so',source=['python_wraper.cpp', 'MapHolder.cpp', 'FooTicTacToe.cpp'], LIBS=boost_libs, SHLIBPREFIX='')
else:
print platform.system() + ' not supported'
If You invoke that Python script:
import cpp_collections
sample_dict = {'EUR':'European','USD':'United States Dolar','RON':'Romanian leu','PLN':'Polish Zloty','HUF':'Hungarian forint', '1':'Number as a text'}
sample_map = cpp_collections.map(sample_dict)
print sample_map.size()
print sample_map.to_dict()
sample_map.update_map({'UKC':'Unknown Currency'})
print sample_map.size()
print sample_map.to_dict()
sample_map.clear();
print sample_map.size()
print sample_map.to_dict()
sample_map.update_map({2:'Number as a number'});
print sample_map.size()
print sample_map.to_dict()
You will see result
6
{'HUF': 'Hungarian forint', 'USD': 'United States Dolar', 'RON': 'Romanian leu', '1': 'Number as a text', 'PLN': 'Polish Zloty', 'EUR': 'European'}
7
{'HUF': 'Hungarian forint', 'USD': 'United States Dolar', 'RON': 'Romanian leu', '1': 'Number as a text', 'PLN': 'Polish Zloty', 'UKC': 'Unknown Currency', 'EUR': 'European'}
0
{}
Key invalid, map might be incomplete
0
{}
So we created working boost::python::dict to std::map converter. Lets use it to create Foo TicTacToe game.
#include "MapHolder.hpp"
#include <boost/python.hpp>
#ifndef FooTicTacToe_HPP
#define FooTicTacToe_HPP
class FooTicTacToe: public MapHolder{
public:
FooTicTacToe();
FooTicTacToe(boost::python::dict& py_dict);
bool FooIsWinner();
};
#endif
and method implementation
#include "FooTicTacToe.hpp"
FooTicTacToe::FooTicTacToe():
MapHolder()
{}
FooTicTacToe::FooTicTacToe(boost::python::dict& py_dict):
MapHolder(py_dict)
{}
bool FooTicTacToe::FooIsWinner(){
//TODO that method is realy stupid
return map_["a1"]=="x" && map_["a2"]=="x" && map_["a3"] =="x";
}
Because we used boost python classes inheritance, we have ready methods to simulate moves. Bellow is Python script to simulate really foo game.
#TicTacToe game
ttt_game = cpp_collections.FooTicTacToe({'a1':'x'})
#make moves
ttt_game.update_map({'b1':'o'})
ttt_game.update_map({'a2':'x'})
print 'Is winner?',ttt_game.is_winner()
ttt_game.update_map({'b2':'0'})
ttt_game.update_map({'a3':'x'})
print 'Is winner?',ttt_game.is_winner()
ttt_game.clear()
It produces output
Is winner? False
Is winner? True