Dear PyROOTers,
I am having troubles to access STL containers in PyROOT. The task is to get certain pieces of legacy code accessible in Python, using PyROOT (I also looked into SWIG and BoostPython, but PyROOT seems to be incredibly flexible).
Currently I am trying to get my head around how to deal with STL maps as return values. The C++ code looks like this:
class Legacy
{
public:
struct MyClass
{
char type;
std::string value;
std::string comment;
template<typename T>
T Get() const
{
T t;
std::istringstream str(value);
str >> t;
return t;
}
};
std::map<std::string, MyClass> map;
Legacy( const char* filename)
{
// opens the file and fills the map...
}
const std::map<std::string, MyClass>& GetMap() const
{
return map;
}
}
In Python, I do mostly this:
>>> from ROOT import gSystem
>>> gSystem.Load('legacy_h.so')
>>> from ROOT import *
>>> l = Lecacy("some file name")
>>> m = l.GetMap()
>>> m
<ROOT.map<string,Legacy::MyClass> object at 0x...>
>>> len(m)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'map<string,Legacy::MyClass,less<string>,allocator<pair<const string,Legacy::MyClass> > >' has no len()
>>> for thing in m:
... print m
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'map<string,Legacy::MyClass,less<string>,allocator<pair<const string,Legacy::MyClass> > >' object is not iterable
Creating and Accessing STL maps of simple types works
>>> import ROOT
>>> m = ROOT.std.map(str,int)()
>>> m['test1'] = 1
>>> m['test2'] = 2
>>> len(m)
2
>>> for i in m:
... print i.first, i.second
...
test1 1
test2 2
The next thing I tested was, what happens If I create a ROOT.std.map(str, Legacy.MyClass) manually instead of using the return value, with the same result. For completeness I did:
>>> import ROOT
>>> ROOT.gSystem.Load("legacy_h.so")
>>> from ROOT import Legacy
>>> m = ROOT.std.map(str, Legacy.MyClass)()
[...took some seconds...]
>>> len(m)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'map<string,Legacy::MyClass,less<string>,allocator<pair<const string,Legacy::MyClass> > >' has no len()
Some AutoDict files were created, I assume during the “m = ROOT.std.map(str, Legacy.MyClass)()” step. They look like:
AutoDict_allocator_pair_const_string_Legacy__MyClass___.cxx
#include "vector"
#include "string"
#include "legacy.h"
#ifdef __CINT__
#pragma link C++ nestedclasses;
#pragma link C++ nestedtypedefs;
#pragma link C++ class allocator<pair<const string,Legacy::MyClass> >+;
#pragma link C++ class allocator<pair<const string,Legacy::MyClass> >::*+;
#endif
AutoDict_pair_const_string_Legacy__MyClass_.cxx
#include "vector"
#include "string"
#include "legacy.h"
#ifdef __CINT__
#pragma link C++ nestedclasses;
#pragma link C++ nestedtypedefs;
#pragma link C++ class pair<const string,Legacy::MyClass>+;
#pragma link C++ class pair<const string,Legacy::MyClass>::*+;
#endif
I wonder If I have to generate some dictionaries myself, before working with these maps(str, Legacy.MyClass) or if the AutoDicts, which are made are actually enough.
Thanks you for your time.