Stuck with using vector<MyObject> and MyObject

Dear forum,

apologies if the answer to this is addressed on the root website or in the forum; I just can’t figure out specifically what I need to do, despite my own attempts!

I have defined my own class, VariableRAlgo, (in fastJetVRClass.cxx and .h), and am able to use this in PyRoot fine (thanks to previous help on here with dictionary generation: Problem generating/using dictionary).

However, I would like to use in my PyRoot code a vector that is returned from one of the member functions of the VariableRAlgo class. Please note: PseudoJet can be used in my fastJetVRClass.* files by just doing #include “fastjet/PseudoJet.hh”

The Makefile and LinkDef that I use to generate the dictionary for the VariableRAlgo, and then compile the code for this class, are attached. If anyone is able to help me with what I should do to use the vector and also the PseudoJet objects themselves, that would be really great. I got as far as being able to use the former, but not the latter.

Many thanks in advance
Sarah
LinkDef.h (289 Bytes)
Makefile.txt (529 Bytes)

Sarah,

adding the following lines to LinkDef.h should do the trick:

#include "fastjet/PseudoJet.hh" #ifdef __CINT__ #pragma link C++ class PseudoJet; #pragma link C++ class std::vector<PseudoJet>; #endif

Btw., not sure why you #include the .cxx in the LinkDef.h? I prefer to keep the LinkDef.h free of #include’s, by having a MyHeader.h and a MyHeader_LinkDef.h, then using this make rule:%_cint.cxx: %.h %_LinkDef.h rootcint -f $@ -c $*.h $*_LinkDef.h
Cheers,
Wim

Hi Wim,

thanks very much for the reply!

Putting everything except the following, in the LinkDef.h, allowed compilation to proceed OK:

#pragma link C++ class PseudoJet;

However, when I put this above line in so that my LinkDef.h looks like the attached (I’ll split the #include statements out later - thanks for the tip, I just do one thing at a time at the moment!), I get the attached compilation error.

I’m not sure what’s going on; would you happen to know?

Thanks very much in advance
Sarah
makeError.txt (3.63 KB)
LinkDef.h.txt (405 Bytes)

Try a “LinkDef.h” which contains just (i.e. only): #ifdef __CINT__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; #pragma link C++ nestedclasses; #pragma link C++ class VariableRAlgo+; #pragma link C++ class PseudoJet+; #pragma link C++ class std::vector<PseudoJet>+; #endif and then: rootcint -f MyDict.cxx -c -p -I/home/livermore/FastJet/fastjet-3.0.2/../fastjet-install/include fastJetVRClass.h fastjet/PseudoJet.hh LinkDef.h or, if it fails, maybe something like: rootcint -f MyDict.cxx -c -p -I/home/livermore/FastJet/fastjet-3.0.2/../fastjet-install/include fastJetVRClass.h /home/livermore/FastJet/fastjet-3.0.2/../fastjet-install/include/fastjet/PseudoJet.hh LinkDef.h

Sarah,

either a header is missing (presumably with a “using namespace fastjet;”), or what is really needed is a fully scoped name:#pragma link C++ class fastjet::PseudoJet;
But those are just guesses. What would help is to see what MyDict.cxx line 669 (and a couple before/after) actually looks like.

Cheers,
Wim

Dear Pepe and Wim,
many thanks for both of your replies! I thought it best to try both since they seem to suggesting separate approaches.

Dictionary creation for both approaches worked, but compilation using the resulting dictionary, alas, did not. However, the compilations failed because of different lines in the MyDict.cxx.

I attach the dictionaries and make outputs, and LinkDef.h files are below (the latter just to confirm what I’m doing) from both attempts. Perhaps demonstration of the different approaches can help to identify what might be going wrong. If either/both of you have an insight, I’d be very grateful!

Thanks very much once again for your help
Sarah

LinkDef.h from Pepe:

#ifdef __CINT__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; #pragma link C++ nestedclasses; #pragma link C++ class VariableRAlgo+; #pragma link C++ class fastjet::PseudoJet+; #pragma link C++ class std::vector<fastjet::PseudoJet>+; #endif

LinkDef.h from Wim:

[code]#include
#include
#include “TString.h”
#include “fastJetVRClass.cxx”
#include “fastjet/PseudoJet.hh”

#ifdef CINT
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;
#pragma link C++ class VariableRAlgo;
#pragma link C++ class fastjet::PseudoJet;
#pragma link C++ class std::vectorfastjet::PseudoJet;
#endif
[/code]
makeErrorWim.txt (3.63 KB)
MyDictWim.cxx.txt (142 KB)
MyDictWim.h.txt (6.39 KB)
makeErrorPepe.txt (3.62 KB)
MyDictPepe.cxx.txt (151 KB)
MyDictPepe.h.txt (6.43 KB)

Sarah,

let me ping Philippe, it looks to me that this generated line:fastjet::PseudoJet::SharedPtr<UserInfoBase>should be:fastjet::PseudoJet::SharedPtr<fastjet::PseudoJet::UserInfoBase>
Cheers,
Wim

Maybe you should also add: // ... #pragma link C++ class VariableRAlgo+; #pragma link C++ namespace fastjet; #pragma link C++ class fastjet::PseudoJet+; // ...

Hi,

from Philippe:[quote]For template to work properly with CINT, one should always use the fully
qualified name in the declaration. I.e. my guess is that

fastjet::PseudoJet::SharedPtr

should be replaced in with

fastjet::PseudoJet::SharedPtrfastjet::PseudoJet::UserInfoBase

in its header file.[/quote]
Cheers,
Wim

Hi Pepe, Wim,
thanks very much again. I change my LinkDef.h to (only):

#ifdef __CINT__ #pragma link off all globals; #pragma link off all classes; #pragma link off all functions; #pragma link C++ nestedclasses; #pragma link C++ class VariableRAlgo+; #pragma link C++ namespace fastjet; #pragma link C++ class fastjet::PseudoJet+; #pragma link C++ class std::vector<fastjet::PseudoJet>+; #endif

I get the attached error with compilation using the generated dictionary. Indeed it still seems to have the following in the MyDict.cxx, which you’ve indicated might be the problem!

const fastjet::PseudoJet::SharedPtr<UserInfoBase>& obj = ((const fastjet::PseudoJet*) G__getstructoffset())->user_info_shared_ptr()\ ;
I did manually amend this to have the following, but got the same error during compliation.

const fastjet::PseudoJet::SharedPtr<fastjet::PseudoJet::UserInfoBase>& obj = ((const fastjet::PseudoJet*) G__getstructoffset())->user_info_shared_ptr()\ ;
Adding the “namespace” line to the Linkdef.h doesn’t seem to have fixed things; do you know what might?

Thanks very much again!
Sarah
MyDict_06Apr.h.txt (6.88 KB)
MyDict_06Apr.cxx.txt (217 KB)
makeError_06Apr.txt (3.66 KB)

I didn’t really think that adding the “namespace” line to the LinkDef.h would fix the problem. It was just a matter of making your LinkDef.h more “complete”.

Maybe you could post the “PseudoJet.hh” file here so that maybe Philippe might take a look inside.

Hi,

Philippe wrote that the change must be in the PseudoJet header file, not in the LinkDef.h.

What I’m thinking you could do, is to add in the local header that you feed rootcint:typedef ::fastjet::PseudoJet::UserInfoBase UserInfoBase;
Cheers,
Wim

Hi Wim, Pepe, Philippe,
sorry for my confusion when translating the advice. I have to admit that my confusion is ongoing… I think the best approach is if I attach PseudoJet.hh and SharedPtr.hh (and also PseudoJetStructureBase.hh in case it is related). Perhaps it will help to see what is needed and where? Wim, I can certainly follow your suggestion for adding the typedef.

Hopefully it will not be too difficult to get this working!

Thanks again
Sarah
SharedPtr.hh (12.7 KB)
PseudoJetStructureBase.hh (8.6 KB)
PseudoJet.hh (36.6 KB)

Dear all,

I was thinking further about this; perhaps it would be less fraught with problems if I use simple vectors of floats in my PyRoot code, rather than attempting to use vector.

It would certainly be optimal in terms of speed and encapsulation to use the latter but I fear that I will keep running into problems and need to bug people :blush:

If you think that it won’t take too much extra work to get the vector useable, I’ll certainly persist. Otherwise, I can see how the vector performs.

Thanks very much in advance for your advice
Sarah

Sarah,

from that I take that the typedef didn’t work? (I tried the example, but the parsing of even fastjet/internal/base.hh fails on rootcint.)

Cheers,
Wim

Hi Wim,

thanks, I gave it a try. Hmm, by “local header” did you mean for me to put it in the header of the wrapper class that I have made, fastJetVRClass.h? That’s what I supply to rootcint (along with LinkDef of course)

[quote]What I’m thinking you could do, is to add in the local header that you feed rootcint:
typedef ::fastjet::PseudoJet::UserInfoBase UserInfoBase;
[/quote]

To confirm what I’m doing now, I attach this fastJetVRClass.h, LinkDef.h, Makefile, MyDict.h, MyDict.cxx and the output from the compilation (compileOutput.txt)

Is some mistake jumping out at you?

It would be nice to get this working for the satisfaction of solving a problem! However I’m thinking that it may actually be more sensible to keep the fastjet classes in this fastJetVRClass that I have written, since it is supposed to be a wrapper for fastjet after all. Then I keep all the fastjet out of Python; my worry is just that I’ll have four times as many vectors being passed out of the wrapper, but perhaps that won’t cost me as much as I think speed-wise.

So, if it looks like this may be very tricky to solve then please don’t take further time on it. But thanks really very much for your help (and Pepe, Philippe)

Sarah
fastJetVRClass.h (1.82 KB)
MyDict.h (6.36 KB)
MyDict.cxx (141 KB)
Makefile.txt (880 Bytes)
LinkDef.h (423 Bytes)
compileOutput.txt (7.3 KB)

Hi,

To get rid of (which is due to your templated constructor):/home/livermore/FastJet/fastjet-3.0.2/../fastjet-install/include/fastjet/PseudoJet.hh: In member function `void fastjet::PseudoJet::reset(const L&) [with L = TRootIOCtor*]': ...add to your class: PseudoJet(TRootIOCtor*) : _px(0), _py(0), _pz(0), _E(0) {_finish_init(); _reset_indices();} // Constructor to be used by ROOT I/O.

As mentioned earlier when using a type as a template argument, to workaround CINT’s limitation, always use the fully qualified name. So for example replace: const SharedPtr<UserInfoBase> & user_info_shared_ptr() const{with const SharedPtr<fastjet::PseudoJet::UserInfoBase> & user_info_shared_ptr() const{(in many places).(and no a typedef does not help here unless the typedef is in the global scope …)

Cheers,
Philippe.

Sarah,

[quote=“SarahL”]thanks, I gave it a try. Hmm, by “local header” did you mean for me to put it in the header of the wrapper class that I have made, fastJetVRClass.h?[/quote]any header that will be picked up by MyDict.cxx will do, so yes, fastJetVRClass.h is good.

The error now points to a problem with SharedPtr: For some reason, the generated code thinks that SharedPtr is part of PseudoJet:const fastjet::PseudoJet::SharedPtr<UserInfoBase>&which it is not (it lives in ::fastjet). Seems like another error in the dictionary generation part …

Not sure how to deal with/work around that issue w/o modifying PseudoJet.hh.

Cheers,
Wim

Hi Wim,

I thought in the end it might be easier to keep the FastJet stuff in fastJetVRClass and not try to use it directly in Python. As you say, I might have to edit the FastJet code itself (like PseudoJet) and that sounds tricky!

The code seems to be working OK though if I pass (out of fastJetVRClass and into PyRoot) vectors of vectors (of the Px, Py, Pz, E of the PseudoJets) rather than trying to pass out the PseudoJets themselves.

Thanks very much for your help (and also Philippe, Pepe) though throughout this thread, I have certainly learnt a lot that I’m sure will be useful in future!

Best,
Sarah