C++ has a bunch of container classes:
- list
- deque
- queue
- priority_queue
- vector
- stack
- map
- multimap
- hash_map
- hash_multimap
- set
- hash_set
- multiset
- hash_multiset
It is not a trivial task to expose C++ container to Python. Boost.Python has a functionality that will help you to expose some of STL containers to Python. This functionality called - "indexing suite". If you want, you can read more about indexing suite here.
Boost.Python, out of the box, supports only vector, map and hash_map containers. In October 2003, Raoul Gough implemented support for the rest of containers. Well, actually he did much more - he implemented new framework. This framework provides support for almost all C++ containers and also an easy way to add support for custom ones. You'd better read his post to Boost.Python mailing list or documentation for the new indexing suite.
Now, I am sure you have next question: if this suite is so good, why it is not in the main branch? The short answer is that this suite has some problems on MSVC 6.0 compiler and there are few users, that still use that compiler. The long answer is here:
Py++ implements support for both indexing suites. More over, you can freely mix indexing suites. For example you can expose std::vector<int> using Boost.Python built-in indexing suite and std::map< int, std::string> using Raoul Gough's indexing suite.
In both cases, Py++ provides almost "hands free" solution. Py++ keeps track of all exported functions and variables, and if it sees that there is a usage of stl container, it exports the container. In both cases, Py++ analyzes the container value_type ( or in case of mapping container mapped_type ), in order to set reasonable defaults, when it generates the code.
By default, Py++ works with built-in indexing suite. If you want to use next version of indexing suite, you should tell this to the module_builder_t.__init__ method:
mb = module_builder_t( ..., indexing_suite_version=2 )
Every declared class has indexing_suite property. If the class is an instantiation of STL container, this property contains reference to an instance of indexing_suite1_t or indexing_suite2_t class.
How does Py++ know, that a class represents STL container instantiation? Well, it uses pygccxml.declarations.container_traits to find out this. pygccxml.declarations.container_traits class, provides all functionality needed to identify container and to find out its value_type ( mapped_type ).
Py++ defines indexing_suite1_t class. This class allows configure any detail of generated code:
no_proxy - a boolean, if value_type is one of the next types
then, no_proxy will be set to True, otherwise to False.
derived_policies - a string, that will be added as is to generated code
element_type - is a reference to container value_type or mapped_type.
In this case there is no single place, where you can configure exported container functionality. Please take a look on next C++ code:
struct item{
...
private:
bool operator==( const item& ) const;
bool operator<( const item& ) const;
};
struct my_data{
std::vector<item> items;
std::map< std::string, item > name2item_mapping;
};
Py++ declarations tree will contains item, my_data, vector<item> and map<string,item> class declarations.
If value_type does not support "equal" or "less than" functionality, sort and search functionality could not be exported.
Py++ class declaration has two properties: equality_comparable and less_than_comparable. The value of those properties is calculated on first invocation. If Py++ can find operator==, that works on value_type, then, equality_comparable property value will be set to True, otherwise to False. Same process is applied on less_than_comparable property.
In our case, Py++ will set both properties to False, thus sort and search functionality will not be exported.
It is the time to introduce indexing_suite2_t class: