How to use SetBranchAddres() ? Role of SetMakeClass()?

I’m a little lost with the logic behind TBranch::SetAddress(), or equivalently, TTree::SetBranchAddress().

I have a splitted tree which contains the member variables of several TObjects. Lets take a simple case, there is an object with event info, which has a scalar member ‘run’ of type Int_t.


file = new TFile("/home/walter/data/s254/musi_1061.root")
tree = (TTree*)gDirectory->Get("tree");
tree->Scan("run")
*        0 *      1061 *
*        1 *      1061 *

Now I try to apply the recipe given on page 217 in User_Guide_3_10.pdf.

Int_t*   pi_buf = (Int_t*) new Int_t[10];
for (Int_t i=0;i<9;i++) pi_buf[i]=-1;

TBranch *b_run = tree->GetBranch("run");
b_run->SetAddress(pi_buf);
b_run->GetEntry(1);

I’d expect to see “1061” in the first element of this array, but what I see is that it is stored in the 7th element of this array.

for (Int_t i=0;i<9;i++) printf("%2d: %4d\n",i,pi_buf[i]);

 0:   -1
 1:   -1
 2:   -1
 3:   -1
 4:   -1
 5:   -1
 6: 1061
 7:   -1
 8:   -1

As a matter of fact, using SetAddress() with a scaler rather than an array, as done here, may lead to a crash sooner or later.

So I looked into what MakeClass is doing, and saw, that the generated code my MakeClass produces a call

fChain->SetMakeClass(1);

And indeed, calling SetMakeClass(1) before the SetAddress() solves the problem, and one gets the data where one expects it.

Questions:

[ul]
[li] What am I missing here ?[/li]
[li] Is there something obvious I overlooking on page 217 ?[/li]
[li] What is the effect of SetMakeClass() ? Being an inline function it isn’t documented (and a nice example, that a method with a trivial implementation does not always have a trivial semantics, thus should be documented and documentable). [/li][/ul]

[quote]What am I missing here ?
Is there something obvious I overlooking on page 217 ? [/quote]
The example at page 215-217 is about a TTree created from a list a indepedent variables and not from objects.

SetMakeClass sets the TTree is some sort of compatibility mode that allow its reading via a set of independant variable (see the result of running TTree::MakeClass on your TTree). In particular it changes the interpretation of the address passed to SetAddress from being the beginning of the object containing the data to being the exact location where the data should be loaded.

If you have the shared library corresponding to your object it is better if you do

MyClass *myobjp = 0;
tree->SetBranchAddress("toplevel",&myobjp);

If you do not have the shared library, the method you stumbled upon is the one correct way of reading the data.

Cheers,
Philippe.