Retrieving a vector<string> from TFile

Hello,

In my C++ code, I have written a vector of strings to a root file. In CINT, I can get it back by:

 vector<string> *svecPtr; gFile->GetObject("names",svecPtr);

How can I do this in Python? I tried the two things below and neither worked.

>>> file = ROOT.TFile.Open ("PEs_seed001.root")
>>> svec = ROOT.vector("string")()
>>> file.Get ("names", svec)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: TObject* TDirectoryFile::Get(const char* namecycle) =>
    takes at most 1 arguments (2 given)
>>> svec = file.Get ("names")

 *** Break *** segmentation violation

Cheers,
Charles

Charles,

I don’t quite understand, you use GetObject() in CINT, but here:>>> file.Get ("names", svec) you use Get(), and yes, in that case there are too many arguments. AFAIK GetObject() should do the trick, but instead of passing it a live std::vector, it should receive a typed null pointer (your original code, with GetObject() works, but the vector pointer will be replaced, leading to a leak). That is, svec = ROOT.MakeNullPointer( ROOT.vector("string") ) file.Get ("names", svec)
As for the crash, is there further information after the segfault?

Cheers,
Wim

Hi Wim,

Thanks for your help! :smiley:

[quote=“wlav”]Charles,

I don’t quite understand, you use GetObject() in CINT, but here:>>> file.Get ("names", svec) you use Get(), and yes, in that case there are too many arguments. AFAIK GetObject() should do the trick, but instead of passing it a live std::vector, it should receive a typed null pointer (your original code, with GetObject() works, but the vector pointer will be replaced, leading to a leak).
[/quote]

I don’t think it will since

vector<string> *svecPtr;

just declares the pointer, but doesn’t new it any memory. It looks a little cleaner (i.e., no casting) than

vector<string> *svecPtr = (vector<string> *)gFile->Get ("names")

Most importantly :smiley:, what you told me works:

>>> import ROOT
>>> file = ROOT.TFile.Open ("PEs_seed023.root")
>>> svec = ROOT.MakeNullPointer( ROOT.vector("string") )
>>> file.GetObject ("names", svec)
>>> svec
<ROOT.vector<string> object at 0x9f94970>
>>> svec.size()
8L
>>> svec.at(0)
'Top'

I’ve added the full text of the segfault as an attachment. Please let me know if there’s any thing else you need.

Thanks again,
Charles
pythonError.txt (2.97 KB)

Charles,

I meant that this python code:[code]>>> file = ROOT.TFile.Open (“PEs_seed001.root”)

svec = ROOT.vector(“string”)()
file.GetObject (“names”, svec)[/code]would leak, not the C++ code, which is fine.

Thanks for the traceback (and the .root file in the other message). I’ll see what I can unearth.

Cheers,
Wim

Hi,

actually, I do know what’s going on … the return value of Get() is a TObject pointer, but an std::vector< std::string > does not derive from TObject, hence the dynamic casting fails. Not sure how I can detect that, though, given that the interface contract is broken by passing an std::vector< std::string >* through a TObject* …

Cheers,
Wim