CINT limitation information

Dear ROOTers,
when trying to load a macro.C with some classes I get this message:
Limitation: Reference member not supported. Please use pointer /opt/root/pro/include/TGenericClassInfo.h:33:
*** Interpreter error recovered ***

Could you point to some resources about this issue? In which contect is exactly reference member not supported? Thanks,

filimon

Hi,

class A { TObject& objRef; // not supported };

References make it difficult for the interpreter and the I/O to initialize the member properly. Simply use a pointer instead.

Axel.

Hi,

Which version of ROOT are you using?
TGenericClassInfo.h should not be included in a macro [and even if it is, it should be ignored by CINT … at least it is ignored in newer version of ROOT].

Cheers,
Philippe.

Hi, I am using 5.15/08 at the moment. I do not include it myself, but I heaviliy use ROOT in my application. If you want I can find out the inclusion sequence. But if this is fixed in 5.16/00 or HEAD it is ok for me to wait a few weeks (I want to release my software with tagged versions of ROOT/AliROOT only). A related question: If there is a reference in a class, would it suffice to use a specially engineered Constructor(TROOTIOConstructor*) or to just make the reference member not persisten by //! ? or is it really not fixable? Thanks,

filimon

Since we are discussing about dictionaries, another question: I really need to have access to a private data member of a base class, specifically a pointer. Which is the most straightforward way to do this. I was looking in TDictionary for something like:
void* GetDataMemberByName(const char* name)
so I can cast it afterwards but I did not find. Any suggestions?

filimon

[quote] or to just make the reference member not persisten by //! ?[/quote]You must make the reference NOT persistent and make sure the default (or I/O if any) constructor properly sets it up.

Cheers,
Philippe

[quote]so I can cast it afterwards but I did not find. Any suggestions? [/quote]You can to use either TClass::GetListOfDataMembers or TClass::GetListOfRealData (which includes also the base class data member and offset). However it might be more practical to use the TStreamerElement from the TStreamerInfo (TClass::GetStreamerInfo).

Cheers,
Philippe

OK, now I am officially lost :unamused:
For the reference topic: Probably you mean NOT persistent, right? In any case, TGenericClassInfo has this problem on my ROOT version. From which version on is it fixed? I do not use myself references I believe, at least not in the context where the error occurs.

For the dictionary: I still could not find a specific way, but these 2 come in mind:

TClass:GetListOfRealData or TClass:GetListOfDataMembers and then get the data member by TList::FindObject
The problem is, the object I am looking for is a raw pointer of some struct not inheriting from TObject. In any case, what is the content of this specific TList returned?

Regarding the TStreamerInfo method, I assume I will get a TStreamerBasicPointer pointer to an object, but then how can I access the real address of the raw object (the private data member) in memory. I can only thing of using somehow the TStreamerElement::GetStreamer::operator() but I do not understand what should be the arguments.

I note that I only need to run anything just once, to get access to this private pointer, so it does not have to be anything simple :smiley:

[quote]For the reference topic: Probably you mean NOT persistent, right?[/quote]Yes that’s what I meant :slight_smile:

[quote] I do not use myself references I believe, at least not in the context where the error occurs. [/quote]Yes you are not the source of the error.
The source of the error is the improper include of TGenericClassInfo.h …

[quote]For the dictionary:[/quote]What are you trying to achieve (I am asking about the big picture). Maybe an alternative tool (like TTreeFormula) that already does the hard stuff, could be useful.

Anyway you best bet is properly something like:TClass *cl = TClass::GetClass(myclass_name); cl->GetStreamerInflo(); // Insure that the list of real data is setup properly TRealData *d = (TRealData*)cl->GetListOfRealData()->FindObject(data_member_name); void *pointer_to_data = ((char*)pointer_to_object) + d-> GetThisOffset();

Cheers,
Philippe

I think these 4 lines is what I want. I have to check the consistency of the data this pointer points to to be sure. Thanks,

filimon

OK, this fails with the message:
Error in TClass::New: cannot create object of class TMySQLServer
The statement that produces this is cl->GetStreamerInfo but if I dont use it nothing works.

if(fServer) delete fServer;
fServer=new TMySQLServer(db, uid, pw);
TClass cl=TMySQLServer::Class();
cl->GetStreamerInfo(); // Insure that the list of real data is setup properly
TRealData d=(TRealData)cl->GetListOfRealData()->FindObject(“fMySQL”);
MYSQL pointer_to_data=(MYSQL)(((char
)fServer)+d->GetThisOffset());
std::cerr << pointer_to_data->user << std::endl;

Hi,

For that case (where the class does not have a default constructor), instead of the GetStreamerInfo, use cl->BuildRealData(fServer);

Cheers,
Philippe.

PS. You may get some of the information more directly by calling fServer->ServerInfo();

OK, now the code looks like this:

if(fServer) delete fServer;
fServer=new TMySQLServer(db, uid, pw);
TClass cl=TMySQLServer::Class();
cl->BuildRealData(fServer); // Insure that the list of real data is setup properly
TRealData d=(TRealData)cl->GetListOfRealData()->FindObject(“fMySQL”);
MYSQL pointer_to_data=(MYSQL)(((char
)fServer)+d->GetThisOffset());
std::cerr << pointer_to_data << std::endl;

The last line produces:

*** Break *** segmentation violation
Using host libthread_db library “/lib/tls/libthread_db.so.1”.
Attaching to program: /proc/29623/exe, process 29623
[Thread debugging using libthread_db enabled]
[New Thread -1208436512 (LWP 29623)]
0x003177a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x0705d473 in __waitpid_nocancel () from /lib/tls/libc.so.6
#2 0x07007359 in do_system () from /lib/tls/libc.so.6
#3 0x0030878d in system () from /lib/tls/libpthread.so.0
#4 0x03096747 in TUnixSystem::Exec () from /opt/root/pro/lib/libCore.so
#5 0x0309bed9 in TUnixSystem::StackTrace () from /opt/root/pro/lib/libCore.so
#6 0x03098b39 in TUnixSystem::DispatchSignals ()
from /opt/root/pro/lib/libCore.so
#7 0x03098c40 in SigHandler () from /opt/root/pro/lib/libCore.so
#8 0x03097e19 in sighandler () from /opt/root/pro/lib/libCore.so
#9
#10 0x0090a207 in amore::core::PoolInterface::Connect (this=0xbff932a4,
db=0x8c7d644 “mysql://host/AMORE”, uid=0x8c7c684 “uid”,
pw=0x8c7c69c “pw”) at /opt/root/pro/include/TRealData.h:55

It seems from the last line that something happens wrong with TRealData::GetThisOffset so the final raw pointer is not the correct address. Any ideas? What I want to do is to override the “Prepared statements” mechanism of TMySqlServer for my work. The only change needed would be to make the private data members of TMySQLServer and TMySQLStatement protected I think.

[quote]What I want to do is to override the “Prepared statements” mechanism of TMySqlServer for my work. The only change needed would be to make the private data members of TMySQLServer and TMySQLStatement protected I think.[/quote]Yes this is the right think to do (this modification has been uploaded to the CVS repository).

Actually what happens is that there is no TRealData object for ‘fMySQL’, hence d is null, hence the crash. There is no TRealData object for ‘fMySQL’, because this data member is not persistent (and hence we do not attempt in any way to calculate its offset).

Cheers,
Philippe

You are right, I just checked on the root prompt that the TRealData pointer is zero. I don’t know how I missed checking that :frowning: I was under the impression that one needed to put //! to avoid persistence. Anyway, thanks for the modification on TMySQLServer. I think also TMySQLStatement needs to have protected data members instead of private. The plan for me was to have amore::core::MySQLServer: public TMySqlServer returning amore::core::MySqlStatement: public TMySQLStatement. I would appreciate it if this final modification would be possible. Thanks,

filimon

[quote]I was under the impression that one needed to put //! to avoid persistence[/quote]You can also set the class version to zero (See ClassDef(TMySQLServer,0);

[quote]I would appreciate it if this final modification would be possible[/quote]I uploaded those modification to the CVS repository.

By the way, what are the changes you are making to “Prepared statements” mechanism of TMySqlServer?

Cheers,
Philippe

Thanks for the modification. I am interested in changing the BLOB (Binary) data handling mechanism. At the moment if follows copy semantics, data are copied internally everytime the statement is executed. I just want TMySQLStatement to transfer whatever is available in a container of pointers at the time of the statement execution, as I think is the case with the native MySQL C API (admitetely I am new to MySQL so this may fail/be incorrect). I have thought of a solution some months ago but at the moment I think the most elegant one is to really create a TMySQLStatementBind class that does the actual binding and provides a reference semantics interface (e.g. SetInt(int* val)) and feed an object of this class as input to TMySQLStatement. In any case I aim for genericity and lightweight implementation but I may finally end up with something that is very specific to my application. cheers,

filimon

If you succeed in keeping your code generic enough, feel free to sent it to us for incorporation in the MySQL plugin :slight_smile:

Thanks,
Philippe

Generally, you are right. MySQL plugin in ROOT (as well as Oracle and ODBC) uses internal memory buffers to get data from database first and than copy it to user buffer when requested.

I see no problem to implement something like you proposing with TMySQLStatementBind class, but it should be general enough to be implemented in the same manner for Oracle, ODBC and Postgres (where statement class are supported).

I also think, that avoiding additional memcpy does not increase performance too much - your performance mostly limited by network and database itself.

Sergey