[ROOT-6243] ttree data for a type with 2d arrays (via Reflex) Created: 22/Apr/14  Updated: 22/Apr/14  Resolved: 22/Apr/14

Status: Closed
Project: ROOT
Component/s: Dictionaries
Affects Version/s: 5.34/00
Fix Version/s: None

Type: Bug Priority: High
Reporter: Sebastien Binet Assignee: Axel Naumann
Resolution: Fixed Votes: 0
Labels: None
Environment:

linux 64b


Development:

 Description   

trying to write this data:

// data2darray.h
class Data2dArray {
 public:
  long I;
  double Array [2][2];
  double Data;
};

with this simple program:

// main.cxx
#include "TTree.h"
#include "TFile.h"
#include "Cintex/Cintex.h"
 
#include "data2darray.h"
 
#include <iostream>
 
int main(int argc, char **argv) {
  ROOT::Cintex::Cintex::Enable();
 
  TFile *f = TFile::Open("event.root", "RECREATE");
  TTree *t = new TTree("tree", "tree");
  Data2dArray *evt = new Data2dArray;
  t->Branch("evt", &evt);
  for (int i = 0; i < 10; i++) {
    evt->I = i;
    evt->Data = i;
    evt->Array[0][0] = i;
    evt->Array[0][1] = 2*i;
    evt->Array[1][0] = -i;
    evt->Array[1][1] = -2*i;
    t->Fill();
  }
  f->Write();
  f->Close();
 
  return 0;
}

the dictionary was created with genreflex:

$ genreflex data2darray.h -s selection.xml --rootmap=data2darray.rootmap
$ $(CXX) -shared -o libdict.so data2darray_rflx.cpp -lReflex -lCintex

selection.xml:

<lcgdict>
  <class name="Data2dArray" />
</lcgdict>

running main and the CINT interpreter:

root [0]   gSystem->Load("libCintex");
root [1]   ROOT::Cintex::Cintex::Enable();
root [2]   gSystem->Load("libdict");
root [3]   f = TFile::Open("event.root");
root [4]   t = (TTree*)f->Get("tree");
root [5]   Data2dArray *evt = NULL;
root [6]   t->SetBranchAddress("evt", &evt);
root [7] t->GetEntry(2);
root [8] evt->I
(long)2
root [9] evt->Data
(double)2.00000000000000000e+00
root [10] evt->Array
(double*)0x1302898
root [11] evt->Array[0]
(double)2.00000000000000000e+00
root [12] evt->Array[1]
(double)4.00000000000000000e+00
root [13] evt->Array[0][0]
Error: Array index out of range Array[0][0] -> [0]  valid upto Array[1] (tmpfile):1:
*** Interpreter error recovered ***

The type information in data2darray_rflx.cpp looks kosher:

namespace {
  ::Reflex::Type type_156 = ::Reflex::TypeBuilder(Reflex::Literal("long"));
  ::Reflex::Type type_void = ::Reflex::TypeBuilder(Reflex::Literal("void"));
  ::Reflex::Type type_141 = ::Reflex::TypeBuilder(Reflex::Literal("double"));
  ::Reflex::Type type_122 = ::Reflex::TypeBuilder(Reflex::Literal("Data2dArray"));
  ::Reflex::Type type_173 = ::Reflex::ArrayBuilder(type_141, 2);
  ::Reflex::Type type_170 = ::Reflex::ArrayBuilder(type_173, 2);
  ::Reflex::Type type_171 = ::Reflex::ReferenceBuilder(type_122);
  ::Reflex::Type type_122c = ::Reflex::ConstBuilder(type_122);
  ::Reflex::Type type_172 = ::Reflex::ReferenceBuilder(type_122c);
} // unnamed namespace
namespace {
  ::Reflex::Type type_156 = ::Reflex::TypeBuilder(Reflex::Literal("long"));
  ::Reflex::Type type_void = ::Reflex::TypeBuilder(Reflex::Literal("void"));
  ::Reflex::Type type_141 = ::Reflex::TypeBuilder(Reflex::Literal("double"));
  ::Reflex::Type type_122 = ::Reflex::TypeBuilder(Reflex::Literal("Data2dArray"));
  ::Reflex::Type type_173 = ::Reflex::ArrayBuilder(type_141, 2);
  ::Reflex::Type type_170 = ::Reflex::ArrayBuilder(type_173, 2);
  ::Reflex::Type type_171 = ::Reflex::ReferenceBuilder(type_122);
  ::Reflex::Type type_122c = ::Reflex::ConstBuilder(type_122);
  ::Reflex::Type type_172 = ::Reflex::ReferenceBuilder(type_122c);
} // unnamed namespace
 
[...]
// Shadow classes to obtain the data member offsets 
namespace __shadow__ {
#ifdef __Data2dArray
#undef __Data2dArray
#endif
class __Data2dArray {
  public:
  __Data2dArray();
  long I;
  double Array[2][2];
  double Data;
};
}
 
//------Delayed data member builder for class Data2dArray -------------------
void __Data2dArray_db_datamem(Reflex::Class* cl) {
  ::Reflex::ClassBuilder(cl)
  .AddDataMember(type_156, Reflex::Literal("I"), OffsetOf(__shadow__::__Data2dArray, I), ::Reflex::PUBLIC)
  .AddDataMember(type_170, Reflex::Literal("Array"), OffsetOf(__shadow__::__Data2dArray, Array), ::Reflex::PUBLIC)
  .AddDataMember(type_141, Reflex::Literal("Data"), OffsetOf(__shadow__::__Data2dArray, Data), ::Reflex::PUBLIC);
}
 

so... what am I missing here ? (am I the first one to generate a dict for a struct holding a 2d-array ?)

-s



 Comments   
Comment by Sebastien Binet [ 22/Apr/14 ]

hum... it seems the bug comes from the Reflex -> Cintex layer:

http://root.cern.ch/gitweb?p=root.git;a=blob;f=cint/cintex/src/ROOTClassEnhancer.cxx;h=9c123639c06df12fd4c57a699d441d4f1008cf00;hb=37e98489b46e48f2dfacc43251f83d5b8ac1c55e#l556

              if( typ.IsArray() ) {
                 std::stringstream s;
                 s << typ.ArrayLength();
                 nam += "[" + s.str() + "]";
              }

should probably read something like:

if( typ.IsArray() ) {
  std::stringstream s;
  s << typ.ArrayLength();
  nam += "[" + s.str() + "]";
  Reflex::Type *elmtyp = typ.ToType();
  while (elmtyp != NULL && elmtyp->IsArray()) {
    std::stringstream elmtstr;
    elmtstr << elmtyp->ArrayLength();
    nam += "[" + elmtstr.str() + "]";
    elmtyp = elmtyp->ToType();
  }
 }

(not tested)

-s

Comment by Philippe Canal [ 22/Apr/14 ]

Hi Sebastien,

This problem has been fixed a couple of weeks ago (commit http://root.cern.ch/gitweb?p=root.git;a=commitdiff;h=8e1569b70272c45ca24b653c8ebf73e33ecd04a5) and will be part of v5.34/19.

Cheers,
Philippe.

Comment by Sebastien Binet [ 22/Apr/14 ]

ah! amazing nobody noticed before

Generated at Sun Sep 22 01:41:08 CEST 2019 using Jira 7.13.1#713001-sha1:5e06076c2d215a6f699b7e5c90ab2fae7ba5a1ce.