Std::map copy data

Hi.

I have a class method that returns a map<string, KResult>, where KResult is a simple class with a few member variables.

On the C++ side, I print to screen the values stored in my map to make sure they are there.

map<string, KResult> MyClass::myMethod()
{
  map<string, KResult> myRes;
  ... do some stuff....
  cout << filling results << endl;
  map["amp"] = KResult("amp", someValue, "ADU");
  ....
 
  cout << returning result << endl;
  //loop over map and print results to cout

  return myRes
}

When I run this in python, I see the values stored in myRes when I print them to string, but the map is empty in python

kamper = MyClass()

myreturn = kamper.myMethod()
print myreturn
print myreturn.__dict__

the code prints to screen:

from c++

from python…

Why is the data not copied over into ‘myresults’ in python? Any ideas?

thanks in advance,
Adam

I get the same problem if I just return a map<string, int>

c++ code:

map<string, int > MyClass::testMe2()
{ 
  map<string, int > myResults;

  myResults["amp"] = 100;
  return myResults;
}

python

>>> import ROOT
>>> ROOT.gSystem.Load("libkamping")
0
>>> k = ROOT.MyClass()
>>> r = k.testMe2()
>>> r
<ROOT.map<string,int> object at 0x10735d2e0>
>>> r.__dict__
{}

i’m sure this has been dealt with by somebody else, but I have had problems finding any discussion on this in the forum.

thanks!
Adam

Adam,

the dict that you print is the local set of data on the instance, which is empty if nothing has been filled in there: it only contains data members added in python, not any in C++, as those are private (and public data members are available through properties, which you’ll find in the dict of the class, not on the instance).

If the iterator and pair have a CINT dictionary available to them, then you should be able to iterate over the entries in the map:for key, value in myreturn: print key, value
Otherwise, you can check the size (myreturn.size()) and access the members (myreturn[“amp”]) like in C++.

Cheers,
Wim

Hi Wim. Thanks for the response. Of course, I did already try this…

The c++ code is

map<string, KResult > KSimpleKamper1::testMe()
{ 
  map<string, KResult > myResults;

  myResults["amp"] = KResult("amp", 100, "ADU");
  return myResults;
}

(MyClass -> KSimpleKamper1)

I then tried this with the other method that returns a map<string, int>

map<string, int > KSimpleKamper1::testMe2()
{ 
  map<string, int > myResults;

  myResults["amp"] = 100;
  return myResults;
}

and the result

I’m using root 5.34/00 on mac osx 10.8, built with clang… i might try to use an earlier version of ROOT to see if it works there.

thanks again for your help!
Adam

hmmmm…

Hi,

like I said, the iterator and pair need to have their CINT dictionaries for the iteration to work. Changing ROOT versions isn’t going to make a difference if those are missing. As recommended above, start with using direct access and size() to see whether the container is empty or not. Then, you can try begin() and end() and you’ll quickly see if the dicts are there (since these are custom classes, I presume not, unless you explicitly requested them when building the dictionary).

If you want a simple case for testing, use std::map<int, int> as that type is available from the pre-built CINT dlls, and thus works “out-of-the-box.”

Cheers,
Wim

Hi Wim.
Okay, I have it working now (indeed, I needed to generate a dictionary with LinkDef.h and include a class map<string,KResult>… before i was generating my dictionary without using a LinkDef.h file and just doing rootcint -f mydict.cxx -c myheader.h+ myheader2.h+… which works fine for many cases.)

in the linkDef file I had to add instructions for maps

but now, I’m stuck again…

My method that returns a map<string,int> is iterable, but clearly the method that returns map<string,KResult> is not, but it does contain data. (Also, there was this RuntimeWarning regarding the pair<string, KResult>. I managed to get this message to go away when I added “#pragma link C++ class std::pair<std::string, KResult>+;” to my LinkDef.h file, but it doesn’t appear to change the behavior of the returned object.

I put the “pragma class link map” lines both at the beginning of the LinkDef file and at the end of the LinkDef file, but the results appeared to be the same.

thanks again for your help,
Adam

sorry… just to prove that my map<string,KResult> contains valid data:

[quote]>>> r[‘amp’].fValue
100.0

r[‘amp’].fUnit
’ADU’

r[‘chi2’].fValue
22.2

r[‘chi2’].fUnit
’’
[/quote]

sweet jesus…

I needed the following lines in my LinkDef file:

#pragma link C++ class std::map<std::string, KResult>+;
#pragma link C++ class std::pair<std::string, KResult>+;
#pragma link C++ class std::map<std::string, KResult>::*;
#pragma link C++ operators std::map<std::string, KResult>::iterator; 
#pragma link C++ operators std::map<std::string, KResult>::const_iterator;
#pragma link C++ operators std::map<std::string, KResult>::reverse_iterator;

Thanks!!!